mirror of
https://github.com/photonstorm/phaser
synced 2024-11-28 07:31:11 +00:00
Add TilemapGPULayer and many shader factory enhancements.
This commit is contained in:
parent
78b4efbf11
commit
aadd767f8d
94 changed files with 4712 additions and 1737 deletions
|
@ -4,6 +4,7 @@
|
|||
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
||||
*/
|
||||
|
||||
var DefaultBitmapTextNodes = require('../../../renderer/webgl/renderNodes/defaults/DefaultBitmapTextNodes');
|
||||
var Class = require('../../../utils/Class');
|
||||
var Clamp = require('../../../math/Clamp');
|
||||
var Components = require('../../components');
|
||||
|
@ -51,7 +52,7 @@ var Render = require('./BitmapTextRender');
|
|||
* @extends Phaser.GameObjects.Components.Mask
|
||||
* @extends Phaser.GameObjects.Components.Origin
|
||||
* @extends Phaser.GameObjects.Components.PostPipeline
|
||||
* @extends Phaser.GameObjects.Components.RenderNode
|
||||
* @extends Phaser.GameObjects.Components.RenderNodes
|
||||
* @extends Phaser.GameObjects.Components.ScrollFactor
|
||||
* @extends Phaser.GameObjects.Components.Texture
|
||||
* @extends Phaser.GameObjects.Components.Tint
|
||||
|
@ -79,7 +80,7 @@ var BitmapText = new Class({
|
|||
Components.Mask,
|
||||
Components.Origin,
|
||||
Components.PostPipeline,
|
||||
Components.RenderNode,
|
||||
Components.RenderNodes,
|
||||
Components.ScrollFactor,
|
||||
Components.Texture,
|
||||
Components.Tint,
|
||||
|
@ -296,12 +297,29 @@ var BitmapText = new Class({
|
|||
this.setTexture(entry.texture, entry.frame);
|
||||
this.setPosition(x, y);
|
||||
this.setOrigin(0, 0);
|
||||
this.initRenderNodes('BitmapText');
|
||||
this.initRenderNodes(this._defaultRenderNodesMap);
|
||||
this.initPostPipeline();
|
||||
|
||||
this.setText(text);
|
||||
},
|
||||
|
||||
/**
|
||||
* The default render nodes to initialize.
|
||||
*
|
||||
* @name Phaser.GameObjects.BitmapText#_defaultRenderNodesMap
|
||||
* @type {Map<string, string>}
|
||||
* @private
|
||||
* @webglOnly
|
||||
* @readonly
|
||||
* @since 3.90.0
|
||||
*/
|
||||
_defaultRenderNodesMap: {
|
||||
get: function ()
|
||||
{
|
||||
return DefaultBitmapTextNodes;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Set the lines of text in this BitmapText to be left-aligned.
|
||||
* This only has any effect if this BitmapText contains more than one line of text.
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
var BlitterRender = require('./BlitterRender');
|
||||
var Bob = require('./Bob');
|
||||
var DefaultBlitterNodes = require('../../renderer/webgl/renderNodes/defaults/DefaultBlitterNodes');
|
||||
var Class = require('../../utils/Class');
|
||||
var Components = require('../components');
|
||||
var Frame = require('../../textures/Frame');
|
||||
|
@ -47,7 +48,7 @@ var List = require('../../structs/List');
|
|||
* @extends Phaser.GameObjects.Components.Lighting
|
||||
* @extends Phaser.GameObjects.Components.Mask
|
||||
* @extends Phaser.GameObjects.Components.PostPipeline
|
||||
* @extends Phaser.GameObjects.Components.RenderNode
|
||||
* @extends Phaser.GameObjects.Components.RenderNodes
|
||||
* @extends Phaser.GameObjects.Components.ScrollFactor
|
||||
* @extends Phaser.GameObjects.Components.Size
|
||||
* @extends Phaser.GameObjects.Components.Texture
|
||||
|
@ -71,7 +72,7 @@ var Blitter = new Class({
|
|||
Components.Lighting,
|
||||
Components.Mask,
|
||||
Components.PostPipeline,
|
||||
Components.RenderNode,
|
||||
Components.RenderNodes,
|
||||
Components.ScrollFactor,
|
||||
Components.Size,
|
||||
Components.Texture,
|
||||
|
@ -88,7 +89,7 @@ var Blitter = new Class({
|
|||
|
||||
this.setTexture(texture, frame);
|
||||
this.setPosition(x, y);
|
||||
this.initRenderNodes('Blitter');
|
||||
this.initRenderNodes(this._defaultRenderNodesMap);
|
||||
this.initPostPipeline();
|
||||
|
||||
/**
|
||||
|
@ -124,6 +125,23 @@ var Blitter = new Class({
|
|||
this.dirty = false;
|
||||
},
|
||||
|
||||
/**
|
||||
* The default render nodes to use for this Game Object.
|
||||
*
|
||||
* @name Phaser.GameObjects.Blitter#_defaultRenderNodesMap
|
||||
* @type {Map<string, string>}
|
||||
* @private
|
||||
* @webglOnly
|
||||
* @readonly
|
||||
* @since 3.90.0
|
||||
*/
|
||||
_defaultRenderNodesMap: {
|
||||
get: function ()
|
||||
{
|
||||
return DefaultBlitterNodes;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates a new Bob in this Blitter.
|
||||
*
|
||||
|
|
155
src/gameobjects/components/ElapseTimer.js
Normal file
155
src/gameobjects/components/ElapseTimer.js
Normal file
|
@ -0,0 +1,155 @@
|
|||
/**
|
||||
* @author Benjamin D. Richards <benjamindrichards@gmail.com>
|
||||
* @copyright 2013-2024 Phaser Studio Inc.
|
||||
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Provides methods for managing an elapse timer on a Game Object.
|
||||
* The timer is used to drive animations and other time-based effects.
|
||||
*
|
||||
* This is not necessary for normal animations.
|
||||
* It is intended to drive shader effects that require a time value.
|
||||
*
|
||||
* If you are adding this component to a Game Object,
|
||||
* ensure that you register a preUpdate method on the Game Object, e.g.:
|
||||
*
|
||||
* ```javascript
|
||||
* // Overrides Game Object method
|
||||
* addedToScene: function ()
|
||||
* {
|
||||
* this.scene.sys.updateList.add(this);
|
||||
* },
|
||||
*
|
||||
* // Overrides Game Object method
|
||||
* removedFromScene: function ()
|
||||
* {
|
||||
* this.scene.sys.updateList.remove(this);
|
||||
* },
|
||||
*
|
||||
* preUpdate: function (time, delta)
|
||||
* {
|
||||
* this.updateTimer(time, delta);
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @namespace Phaser.GameObjects.Components.ElapseTimer
|
||||
* @since 3.90.0
|
||||
*/
|
||||
var ElapseTimer = {
|
||||
|
||||
/**
|
||||
* The time elapsed since timer initialization, in milliseconds.
|
||||
*
|
||||
* @name Phaser.GameObjects.Components.ElapseTimer#timeElapsed
|
||||
* @type {number}
|
||||
* @since 3.90.0
|
||||
*/
|
||||
timeElapsed: 0,
|
||||
|
||||
/**
|
||||
* The time after which `timeElapsed` will reset, in milliseconds.
|
||||
* By default, this is 1 hour.
|
||||
* If you use the timer for animations, you can set this to a period
|
||||
* that matches the animation durations.
|
||||
*
|
||||
* This is necessary for the timer to avoid floating-point precision issues
|
||||
* in shaders.
|
||||
* A float32 can represent a few hours of milliseconds accurately,
|
||||
* but the precision decreases as the value increases.
|
||||
*
|
||||
* @name Phaser.GameObjects.Components.ElapseTimer#timeElapsedResetPeriod
|
||||
* @type {number}
|
||||
* @since 3.90.0
|
||||
* @default 3600000
|
||||
*/
|
||||
timeElapsedResetPeriod: 60 * 60 * 1000,
|
||||
|
||||
/**
|
||||
* Whether the elapse timer is paused.
|
||||
*
|
||||
* @name Phaser.GameObjects.Components.ElapseTimer#timePaused
|
||||
* @type {boolean}
|
||||
* @since 3.90.0
|
||||
* @default false
|
||||
*/
|
||||
timePaused: false,
|
||||
|
||||
/**
|
||||
* Set the reset period for the elapse timer for this game object.
|
||||
*
|
||||
* @method Phaser.GameObjects.Components.ElapseTimer#setTimerResetPeriod
|
||||
* @since 3.90.0
|
||||
* @param {number} period - The time after which `timeElapsed` will reset, in milliseconds.
|
||||
* @return {this} This game object.
|
||||
*/
|
||||
setTimerResetPeriod: function (period)
|
||||
{
|
||||
this.timeElapsedResetPeriod = period;
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Pauses or resumes the elapse timer for this game object.
|
||||
*
|
||||
* @method Phaser.GameObjects.Components.ElapseTimer#setTimerPaused
|
||||
* @since 3.90.0
|
||||
* @param {boolean} [paused] - Pause state (`true` to pause, `false` to unpause). If not specified, the timer will unpause.
|
||||
* @return {this} This game object.
|
||||
*/
|
||||
setTimerPaused: function (paused)
|
||||
{
|
||||
this.timePaused = !!paused;
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Reset the elapse timer for this game object.
|
||||
*
|
||||
* @method Phaser.GameObjects.Components.ElapseTimer#resetTimer
|
||||
* @since 3.90.0
|
||||
* @param {number} [ms=0] - The time to reset the timer to.
|
||||
* @return {this} This game object.
|
||||
*/
|
||||
resetTimer: function (ms)
|
||||
{
|
||||
if (ms === undefined) { ms = 0; }
|
||||
this.timeElapsed = ms;
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Update the elapse timer for this game object.
|
||||
* This should be called automatically by the preUpdate method.
|
||||
*
|
||||
* Override this method to create more advanced time management,
|
||||
* or set it to a NOOP function to disable the timer update.
|
||||
* If you want to control animations with a tween or input system,
|
||||
* disabling the timer update could be useful.
|
||||
*
|
||||
* @method Phaser.GameObjects.Components.ElapseTimer#updateTimer
|
||||
* @since 3.90.0
|
||||
* @param {number} time - The current time in milliseconds.
|
||||
* @param {number} delta - The time since the last update, in milliseconds.
|
||||
* @return {this} This game object.
|
||||
*/
|
||||
updateTimer: function (time, delta)
|
||||
{
|
||||
if (!this.timePaused)
|
||||
{
|
||||
this.timeElapsed += delta;
|
||||
|
||||
if (this.timeElapsed >= this.timeElapsedResetPeriod)
|
||||
{
|
||||
this.timeElapsed -= this.timeElapsedResetPeriod;
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = ElapseTimer;
|
|
@ -9,11 +9,11 @@ var DeepCopy = require('../../utils/object/DeepCopy');
|
|||
/**
|
||||
* Provides methods for setting the WebGL render nodes of a Game Object.
|
||||
*
|
||||
* @namespace Phaser.GameObjects.Components.RenderNode
|
||||
* @namespace Phaser.GameObjects.Components.RenderNodes
|
||||
* @webglOnly
|
||||
* @since 3.90.0
|
||||
*/
|
||||
var RenderNode = {
|
||||
var RenderNodes = {
|
||||
/**
|
||||
* Customized WebGL render nodes of this Game Object.
|
||||
* RenderNodes are responsible for managing the rendering process of this Game Object.
|
||||
|
@ -69,7 +69,7 @@ var RenderNode = {
|
|||
* @method Phaser.GameObjects.Components.RenderNode#initRenderNodes
|
||||
* @webglOnly
|
||||
* @since 3.90.0
|
||||
* @param {string|Map<string, string>} defaultNodes - The default render nodes to set for this Game Object. This can be a string referring to a map in the RenderNodeManager, or a map of render nodes to set directly.
|
||||
* @param {Map<string, string>} defaultNodes - The default render nodes to set for this Game Object.
|
||||
*/
|
||||
initRenderNodes: function (defaultNodes)
|
||||
{
|
||||
|
@ -84,27 +84,17 @@ var RenderNode = {
|
|||
return;
|
||||
}
|
||||
|
||||
var manager = this.scene.sys.renderer.renderNodes;
|
||||
var manager = renderer.renderNodes;
|
||||
|
||||
if (!manager)
|
||||
if (!(manager && defaultNodes))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof defaultNodes === 'string')
|
||||
{
|
||||
defaultNodes = manager.defaultRenderNodes[defaultNodes];
|
||||
}
|
||||
|
||||
if (!defaultNodes)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var _this = this;
|
||||
var defaultRenderNodes = this.defaultRenderNodes;
|
||||
defaultNodes.each(function (role, node)
|
||||
{
|
||||
_this.defaultRenderNodes[role] = manager.getNode(node);
|
||||
defaultRenderNodes[role] = manager.getNode(node);
|
||||
});
|
||||
},
|
||||
|
||||
|
@ -212,4 +202,4 @@ var RenderNode = {
|
|||
}
|
||||
};
|
||||
|
||||
module.exports = RenderNode;
|
||||
module.exports = RenderNodes;
|
|
@ -16,6 +16,7 @@ module.exports = {
|
|||
ComputedSize: require('./ComputedSize'),
|
||||
Crop: require('./Crop'),
|
||||
Depth: require('./Depth'),
|
||||
ElapseTimer: require('./ElapseTimer'),
|
||||
Flip: require('./Flip'),
|
||||
FX: require('./FX'),
|
||||
GetBounds: require('./GetBounds'),
|
||||
|
@ -25,7 +26,7 @@ module.exports = {
|
|||
PathFollower: require('./PathFollower'),
|
||||
Pipeline: require('./Pipeline'),
|
||||
PostPipeline: require('./PostPipeline'),
|
||||
RenderNode: require('./RenderNode'),
|
||||
RenderNodes: require('./RenderNodes'),
|
||||
ScrollFactor: require('./ScrollFactor'),
|
||||
Size: require('./Size'),
|
||||
Texture: require('./Texture'),
|
||||
|
|
|
@ -10,6 +10,7 @@ var Commands = require('./Commands');
|
|||
var Components = require('../components');
|
||||
var Ellipse = require('../../geom/ellipse/Ellipse');
|
||||
var GameObject = require('../GameObject');
|
||||
var DefaultGraphicsNodes = require('../../renderer/webgl/renderNodes/defaults/DefaultGraphicsNodes.js');
|
||||
var GetFastValue = require('../../utils/object/GetFastValue');
|
||||
var GetValue = require('../../utils/object/GetValue');
|
||||
var MATH_CONST = require('../../math/const');
|
||||
|
@ -74,6 +75,7 @@ var Render = require('./GraphicsRender');
|
|||
* @extends Phaser.GameObjects.Components.Mask
|
||||
* @extends Phaser.GameObjects.Components.Pipeline
|
||||
* @extends Phaser.GameObjects.Components.PostPipeline
|
||||
* @extends Phaser.GameObjects.Components.RenderNodes
|
||||
* @extends Phaser.GameObjects.Components.Transform
|
||||
* @extends Phaser.GameObjects.Components.Visible
|
||||
* @extends Phaser.GameObjects.Components.ScrollFactor
|
||||
|
@ -92,7 +94,7 @@ var Graphics = new Class({
|
|||
Components.Lighting,
|
||||
Components.Mask,
|
||||
Components.PostPipeline,
|
||||
Components.RenderNode,
|
||||
Components.RenderNodes,
|
||||
Components.Transform,
|
||||
Components.Visible,
|
||||
Components.ScrollFactor,
|
||||
|
@ -109,7 +111,7 @@ var Graphics = new Class({
|
|||
GameObject.call(this, scene, 'Graphics');
|
||||
|
||||
this.setPosition(x, y);
|
||||
this.initRenderNodes('Graphics');
|
||||
this.initRenderNodes(this._defaultRenderNodesMap);
|
||||
this.initPostPipeline();
|
||||
|
||||
/**
|
||||
|
@ -239,6 +241,23 @@ var Graphics = new Class({
|
|||
this.setDefaultStyles(options);
|
||||
},
|
||||
|
||||
/**
|
||||
* The default render nodes for this Game Object.
|
||||
*
|
||||
* @name Phaser.GameObjects.Graphics#_defaultRenderNodesMap
|
||||
* @type {Map<string, string>}
|
||||
* @private
|
||||
* @webglOnly
|
||||
* @readonly
|
||||
* @since 3.90.0
|
||||
*/
|
||||
_defaultRenderNodesMap: {
|
||||
get: function ()
|
||||
{
|
||||
return DefaultGraphicsNodes;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Set the default style settings for this Graphics object.
|
||||
*
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
||||
*/
|
||||
|
||||
var DefaultImageNodes = require('../../renderer/webgl/renderNodes/defaults/DefaultImageNodes');
|
||||
var Class = require('../../utils/Class');
|
||||
var Components = require('../components');
|
||||
var GameObject = require('../GameObject');
|
||||
|
@ -33,7 +34,7 @@ var ImageRender = require('./ImageRender');
|
|||
* @extends Phaser.GameObjects.Components.Mask
|
||||
* @extends Phaser.GameObjects.Components.Origin
|
||||
* @extends Phaser.GameObjects.Components.PostPipeline
|
||||
* @extends Phaser.GameObjects.Components.RenderNode
|
||||
* @extends Phaser.GameObjects.Components.RenderNodes
|
||||
* @extends Phaser.GameObjects.Components.ScrollFactor
|
||||
* @extends Phaser.GameObjects.Components.Size
|
||||
* @extends Phaser.GameObjects.Components.TextureCrop
|
||||
|
@ -61,7 +62,7 @@ var Image = new Class({
|
|||
Components.Mask,
|
||||
Components.Origin,
|
||||
Components.PostPipeline,
|
||||
Components.RenderNode,
|
||||
Components.RenderNodes,
|
||||
Components.ScrollFactor,
|
||||
Components.Size,
|
||||
Components.TextureCrop,
|
||||
|
@ -91,8 +92,25 @@ var Image = new Class({
|
|||
this.setPosition(x, y);
|
||||
this.setSizeToFrame();
|
||||
this.setOriginFromFrame();
|
||||
this.initRenderNodes('Image');
|
||||
this.initRenderNodes(this._defaultRenderNodesMap);
|
||||
this.initPostPipeline(true);
|
||||
},
|
||||
|
||||
/**
|
||||
* The default render nodes for this Game Object.
|
||||
*
|
||||
* @name Phaser.GameObjects.Image#_defaultRenderNodesMap
|
||||
* @type {Map<string, string>}
|
||||
* @private
|
||||
* @webglOnly
|
||||
* @readonly
|
||||
* @since 3.90.0
|
||||
*/
|
||||
_defaultRenderNodesMap: {
|
||||
get: function ()
|
||||
{
|
||||
return DefaultImageNodes;
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
||||
*/
|
||||
|
||||
var DefaultNineSliceNodes = require('../../renderer/webgl/renderNodes/defaults/DefaultNineSliceNodes');
|
||||
var Class = require('../../utils/Class');
|
||||
var Components = require('../components');
|
||||
var GameObject = require('../GameObject');
|
||||
|
@ -100,7 +101,7 @@ var Vertex = require('../../geom/mesh/Vertex');
|
|||
* @extends Phaser.GameObjects.Components.Mask
|
||||
* @extends Phaser.GameObjects.Components.Origin
|
||||
* @extends Phaser.GameObjects.Components.PostPipeline
|
||||
* @extends Phaser.GameObjects.Components.RenderNode
|
||||
* @extends Phaser.GameObjects.Components.RenderNodes
|
||||
* @extends Phaser.GameObjects.Components.ScrollFactor
|
||||
* @extends Phaser.GameObjects.Components.Texture
|
||||
* @extends Phaser.GameObjects.Components.Transform
|
||||
|
@ -130,7 +131,7 @@ var NineSlice = new Class({
|
|||
Components.Mask,
|
||||
Components.Origin,
|
||||
Components.PostPipeline,
|
||||
Components.RenderNode,
|
||||
Components.RenderNodes,
|
||||
Components.ScrollFactor,
|
||||
Components.Texture,
|
||||
Components.Transform,
|
||||
|
@ -333,10 +334,27 @@ var NineSlice = new Class({
|
|||
|
||||
this.updateDisplayOrigin();
|
||||
|
||||
this.initRenderNodes('NineSlice');
|
||||
this.initRenderNodes(this._defaultRenderNodesMap);
|
||||
this.initPostPipeline();
|
||||
},
|
||||
|
||||
/**
|
||||
* The default render nodes for this Game Object.
|
||||
*
|
||||
* @name Phaser.GameObjects.NineSlice#_defaultRenderNodesMap
|
||||
* @type {Map<string, string>}
|
||||
* @private
|
||||
* @webglOnly
|
||||
* @readonly
|
||||
* @since 3.90.0
|
||||
*/
|
||||
_defaultRenderNodesMap: {
|
||||
get: function ()
|
||||
{
|
||||
return DefaultNineSliceNodes;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Resets the width, height and slices for this NineSlice Game Object.
|
||||
*
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
||||
*/
|
||||
|
||||
var DefaultParticleEmitterNodes = require('../../renderer/webgl/renderNodes/defaults/DefaultParticleEmitterNodes');
|
||||
var Class = require('../../utils/Class');
|
||||
var Components = require('../components');
|
||||
var ComponentsToJSON = require('../components/ToJSON');
|
||||
|
@ -322,7 +323,7 @@ var configOpMap = [
|
|||
* @extends Phaser.GameObjects.Components.Lighting
|
||||
* @extends Phaser.GameObjects.Components.Mask
|
||||
* @extends Phaser.GameObjects.Components.PostPipeline
|
||||
* @extends Phaser.GameObjects.Components.RenderNode
|
||||
* @extends Phaser.GameObjects.Components.RenderNodes
|
||||
* @extends Phaser.GameObjects.Components.ScrollFactor
|
||||
* @extends Phaser.GameObjects.Components.Texture
|
||||
* @extends Phaser.GameObjects.Components.Transform
|
||||
|
@ -345,7 +346,7 @@ var ParticleEmitter = new Class({
|
|||
Components.Lighting,
|
||||
Components.Mask,
|
||||
Components.PostPipeline,
|
||||
Components.RenderNode,
|
||||
Components.RenderNodes,
|
||||
Components.ScrollFactor,
|
||||
Components.Texture,
|
||||
Components.Transform,
|
||||
|
@ -896,7 +897,7 @@ var ParticleEmitter = new Class({
|
|||
*/
|
||||
this.tintFill = false;
|
||||
|
||||
this.initRenderNodes('ParticleEmitter');
|
||||
this.initRenderNodes(this._defaultRenderNodesMap);
|
||||
this.initPostPipeline();
|
||||
|
||||
this.setPosition(x, y);
|
||||
|
@ -908,6 +909,23 @@ var ParticleEmitter = new Class({
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* The default render nodes for this Game Object.
|
||||
*
|
||||
* @name Phaser.GameObjects.Particles.ParticleEmitter#_defaultRenderNodesMap
|
||||
* @type {Map<string, string>}
|
||||
* @private
|
||||
* @webglOnly
|
||||
* @readonly
|
||||
* @since 3.90.0
|
||||
*/
|
||||
_defaultRenderNodesMap: {
|
||||
get: function ()
|
||||
{
|
||||
return DefaultParticleEmitterNodes;
|
||||
}
|
||||
},
|
||||
|
||||
// Overrides Game Object method
|
||||
addedToScene: function ()
|
||||
{
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
||||
*/
|
||||
|
||||
var DefaultPointLightNodes = require('../../renderer/webgl/renderNodes/defaults/DefaultPointLightNodes');
|
||||
var Class = require('../../utils/Class');
|
||||
var Components = require('../components');
|
||||
var GameObject = require('../GameObject');
|
||||
|
@ -48,7 +49,7 @@ var Render = require('./PointLightRender');
|
|||
* @extends Phaser.GameObjects.Components.GetBounds
|
||||
* @extends Phaser.GameObjects.Components.Mask
|
||||
* @extends Phaser.GameObjects.Components.PostPipeline
|
||||
* @extends Phaser.GameObjects.Components.RenderNode
|
||||
* @extends Phaser.GameObjects.Components.RenderNodes
|
||||
* @extends Phaser.GameObjects.Components.ScrollFactor
|
||||
* @extends Phaser.GameObjects.Components.Transform
|
||||
* @extends Phaser.GameObjects.Components.Visible
|
||||
|
@ -71,7 +72,7 @@ var PointLight = new Class({
|
|||
Components.Depth,
|
||||
Components.Mask,
|
||||
Components.PostPipeline,
|
||||
Components.RenderNode,
|
||||
Components.RenderNodes,
|
||||
Components.ScrollFactor,
|
||||
Components.Transform,
|
||||
Components.Visible,
|
||||
|
@ -89,7 +90,7 @@ var PointLight = new Class({
|
|||
|
||||
GameObject.call(this, scene, 'PointLight');
|
||||
|
||||
this.initRenderNodes('PointLight');
|
||||
this.initRenderNodes(this._defaultRenderNodesMap);
|
||||
this.initPostPipeline();
|
||||
|
||||
this.setPosition(x, y);
|
||||
|
@ -136,6 +137,23 @@ var PointLight = new Class({
|
|||
this._radius = radius;
|
||||
},
|
||||
|
||||
/**
|
||||
* The default render nodes for this Game Object.
|
||||
*
|
||||
* @name Phaser.GameObjects.PointLight#_defaultRenderNodesMap
|
||||
* @type {Map<string, string>}
|
||||
* @private
|
||||
* @webglOnly
|
||||
* @readonly
|
||||
* @since 3.90.0
|
||||
*/
|
||||
_defaultRenderNodesMap: {
|
||||
get: function ()
|
||||
{
|
||||
return DefaultPointLightNodes;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* The radius of the Point Light.
|
||||
*
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
|
||||
var AnimationState = require('../../animations/AnimationState');
|
||||
var DefaultRopeNodes = require('../../renderer/webgl/renderNodes/defaults/DefaultRopeNodes');
|
||||
var Class = require('../../utils/Class');
|
||||
var Components = require('../components');
|
||||
var GameObject = require('../GameObject');
|
||||
|
@ -38,7 +39,7 @@ var Vector2 = require('../../math/Vector2');
|
|||
* @extends Phaser.GameObjects.Components.Flip
|
||||
* @extends Phaser.GameObjects.Components.Mask
|
||||
* @extends Phaser.GameObjects.Components.PostPipeline
|
||||
* @extends Phaser.GameObjects.Components.RenderNode
|
||||
* @extends Phaser.GameObjects.Components.RenderNodes
|
||||
* @extends Phaser.GameObjects.Components.Size
|
||||
* @extends Phaser.GameObjects.Components.Texture
|
||||
* @extends Phaser.GameObjects.Components.Transform
|
||||
|
@ -66,7 +67,7 @@ var Rope = new Class({
|
|||
Components.Flip,
|
||||
Components.Mask,
|
||||
Components.PostPipeline,
|
||||
Components.RenderNode,
|
||||
Components.RenderNodes,
|
||||
Components.Size,
|
||||
Components.Texture,
|
||||
Components.Transform,
|
||||
|
@ -276,7 +277,7 @@ var Rope = new Class({
|
|||
this.setTexture(texture, frame);
|
||||
this.setPosition(x, y);
|
||||
this.setSizeToFrame();
|
||||
this.initRenderNodes('Rope');
|
||||
this.initRenderNodes(this._defaultRenderNodesMap);
|
||||
this.initPostPipeline();
|
||||
|
||||
if (Array.isArray(points))
|
||||
|
@ -289,6 +290,23 @@ var Rope = new Class({
|
|||
this.updateVertices();
|
||||
},
|
||||
|
||||
/**
|
||||
* The default render nodes for this Game Object.
|
||||
*
|
||||
* @name Phaser.GameObjects.Rope#_defaultRenderNodesMap
|
||||
* @type {Map<string, string>}
|
||||
* @private
|
||||
* @webglOnly
|
||||
* @readonly
|
||||
* @since 3.90.0
|
||||
*/
|
||||
_defaultRenderNodesMap: {
|
||||
get: function ()
|
||||
{
|
||||
return DefaultRopeNodes;
|
||||
}
|
||||
},
|
||||
|
||||
// Overrides Game Object method
|
||||
addedToScene: function ()
|
||||
{
|
||||
|
|
|
@ -6,6 +6,11 @@
|
|||
|
||||
var GetCalcMatrix = require('../GetCalcMatrix');
|
||||
|
||||
var renderOptions = {
|
||||
multiTexturing: false,
|
||||
smoothPixelArt: false
|
||||
};
|
||||
|
||||
/**
|
||||
* Renders this Game Object with the WebGL Renderer to the given Camera.
|
||||
* The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera.
|
||||
|
@ -32,6 +37,19 @@ var RopeWebGLRenderer = function (renderer, src, drawingContext, parentMatrix)
|
|||
src.updateVertices();
|
||||
}
|
||||
|
||||
// Get smooth pixel art option.
|
||||
var smoothPixelArt;
|
||||
var srcTexture = src.texture;
|
||||
if (srcTexture && srcTexture.smoothPixelArt !== null)
|
||||
{
|
||||
smoothPixelArt = srcTexture.smoothPixelArt;
|
||||
}
|
||||
else
|
||||
{
|
||||
smoothPixelArt = src.scene.game.config.smoothPixelArt;
|
||||
}
|
||||
renderOptions.smoothPixelArt = smoothPixelArt;
|
||||
|
||||
(src.customRenderNodes.BatchHandler || src.defaultRenderNodes.BatchHandler).batch(
|
||||
drawingContext,
|
||||
src,
|
||||
|
@ -43,7 +61,8 @@ var RopeWebGLRenderer = function (renderer, src, drawingContext, parentMatrix)
|
|||
src.alphas,
|
||||
src.alpha,
|
||||
src.tintFill,
|
||||
src.debugCallback
|
||||
src.debugCallback,
|
||||
renderOptions
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
||||
*/
|
||||
|
||||
var DefaultGraphicsNodes = require('../../renderer/webgl/renderNodes/defaults/DefaultGraphicsNodes');
|
||||
var Class = require('../../utils/Class');
|
||||
var Components = require('../components');
|
||||
var GameObject = require('../GameObject');
|
||||
|
@ -31,7 +32,7 @@ var Line = require('../../geom/line/Line');
|
|||
* @extends Phaser.GameObjects.Components.Mask
|
||||
* @extends Phaser.GameObjects.Components.Origin
|
||||
* @extends Phaser.GameObjects.Components.PostPipeline
|
||||
* @extends Phaser.GameObjects.Components.RenderNode
|
||||
* @extends Phaser.GameObjects.Components.RenderNodes
|
||||
* @extends Phaser.GameObjects.Components.ScrollFactor
|
||||
* @extends Phaser.GameObjects.Components.Transform
|
||||
* @extends Phaser.GameObjects.Components.Visible
|
||||
|
@ -53,7 +54,7 @@ var Shape = new Class({
|
|||
Components.Mask,
|
||||
Components.Origin,
|
||||
Components.PostPipeline,
|
||||
Components.RenderNode,
|
||||
Components.RenderNodes,
|
||||
Components.ScrollFactor,
|
||||
Components.Transform,
|
||||
Components.Visible
|
||||
|
@ -210,10 +211,27 @@ var Shape = new Class({
|
|||
*/
|
||||
this.height = 0;
|
||||
|
||||
this.initRenderNodes('Graphics');
|
||||
this.initRenderNodes(this._defaultRenderNodesMap);
|
||||
this.initPostPipeline();
|
||||
},
|
||||
|
||||
/**
|
||||
* The default render nodes for this Game Object.
|
||||
*
|
||||
* @name Phaser.GameObjects.Shape#_defaultRenderNodesMap
|
||||
* @type {Map<string, string>}
|
||||
* @private
|
||||
* @webglOnly
|
||||
* @readonly
|
||||
* @since 3.90.0
|
||||
*/
|
||||
_defaultRenderNodesMap: {
|
||||
get: function ()
|
||||
{
|
||||
return DefaultGraphicsNodes;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets the fill color and alpha for this Shape.
|
||||
*
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
|
||||
var AnimationState = require('../../animations/AnimationState');
|
||||
var DefaultImageNodes = require('../../renderer/webgl/renderNodes/defaults/DefaultImageNodes');
|
||||
var Class = require('../../utils/Class');
|
||||
var Components = require('../components');
|
||||
var GameObject = require('../GameObject');
|
||||
|
@ -37,7 +38,7 @@ var SpriteRender = require('./SpriteRender');
|
|||
* @extends Phaser.GameObjects.Components.Mask
|
||||
* @extends Phaser.GameObjects.Components.Origin
|
||||
* @extends Phaser.GameObjects.Components.PostPipeline
|
||||
* @extends Phaser.GameObjects.Components.RenderNode
|
||||
* @extends Phaser.GameObjects.Components.RenderNodes
|
||||
* @extends Phaser.GameObjects.Components.ScrollFactor
|
||||
* @extends Phaser.GameObjects.Components.Size
|
||||
* @extends Phaser.GameObjects.Components.TextureCrop
|
||||
|
@ -65,7 +66,7 @@ var Sprite = new Class({
|
|||
Components.Mask,
|
||||
Components.Origin,
|
||||
Components.PostPipeline,
|
||||
Components.RenderNode,
|
||||
Components.RenderNodes,
|
||||
Components.ScrollFactor,
|
||||
Components.Size,
|
||||
Components.TextureCrop,
|
||||
|
@ -108,10 +109,27 @@ var Sprite = new Class({
|
|||
this.setPosition(x, y);
|
||||
this.setSizeToFrame();
|
||||
this.setOriginFromFrame();
|
||||
this.initRenderNodes('Image');
|
||||
this.initRenderNodes(this._defaultRenderNodesMap);
|
||||
this.initPostPipeline(true);
|
||||
},
|
||||
|
||||
/**
|
||||
* The default render nodes for this Game Object.
|
||||
*
|
||||
* @name Phaser.GameObjects.Sprite#_defaultRenderNodesMap
|
||||
* @type {Map<string, string>}
|
||||
* @private
|
||||
* @webglOnly
|
||||
* @readonly
|
||||
* @since 3.90.0
|
||||
*/
|
||||
_defaultRenderNodesMap: {
|
||||
get: function ()
|
||||
{
|
||||
return DefaultImageNodes;
|
||||
}
|
||||
},
|
||||
|
||||
// Overrides Game Object method
|
||||
addedToScene: function ()
|
||||
{
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
var AddToDOM = require('../../dom/AddToDOM');
|
||||
var CanvasPool = require('../../display/canvas/CanvasPool');
|
||||
var DefaultImageNodes = require('../../renderer/webgl/renderNodes/defaults/DefaultImageNodes');
|
||||
var Class = require('../../utils/Class');
|
||||
var Components = require('../components');
|
||||
var GameObject = require('../GameObject');
|
||||
|
@ -69,7 +70,7 @@ var UUID = require('../../utils/string/UUID');
|
|||
* @extends Phaser.GameObjects.Components.Mask
|
||||
* @extends Phaser.GameObjects.Components.Origin
|
||||
* @extends Phaser.GameObjects.Components.PostPipeline
|
||||
* @extends Phaser.GameObjects.Components.RenderNode
|
||||
* @extends Phaser.GameObjects.Components.RenderNodes
|
||||
* @extends Phaser.GameObjects.Components.ScrollFactor
|
||||
* @extends Phaser.GameObjects.Components.Tint
|
||||
* @extends Phaser.GameObjects.Components.Transform
|
||||
|
@ -99,7 +100,7 @@ var Text = new Class({
|
|||
Components.Mask,
|
||||
Components.Origin,
|
||||
Components.PostPipeline,
|
||||
Components.RenderNode,
|
||||
Components.RenderNodes,
|
||||
Components.ScrollFactor,
|
||||
Components.Tint,
|
||||
Components.Transform,
|
||||
|
@ -127,7 +128,7 @@ var Text = new Class({
|
|||
|
||||
this.setPosition(x, y);
|
||||
this.setOrigin(0, 0);
|
||||
this.initRenderNodes('Image');
|
||||
this.initRenderNodes(this._defaultRenderNodesMap);
|
||||
this.initPostPipeline(true);
|
||||
|
||||
/**
|
||||
|
@ -308,6 +309,23 @@ var Text = new Class({
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* The default render nodes for this Game Object.
|
||||
*
|
||||
* @name Phaser.GameObjects.Text#_defaultRenderNodesMap
|
||||
* @type {Map<string, string>}
|
||||
* @private
|
||||
* @webglOnly
|
||||
* @readonly
|
||||
* @since 3.90.0
|
||||
*/
|
||||
_defaultRenderNodesMap: {
|
||||
get: function ()
|
||||
{
|
||||
return DefaultImageNodes;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Initialize right to left text.
|
||||
*
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
var AnimationState = require('../../animations/AnimationState');
|
||||
var CanvasPool = require('../../display/canvas/CanvasPool');
|
||||
var DefaultTileSpriteNodes = require('../../renderer/webgl/renderNodes/defaults/DefaultTileSpriteNodes');
|
||||
var Class = require('../../utils/Class');
|
||||
var Components = require('../components');
|
||||
var GameObject = require('../GameObject');
|
||||
|
@ -54,7 +55,7 @@ var _FLAG = 8; // 1000
|
|||
* @extends Phaser.GameObjects.Components.Mask
|
||||
* @extends Phaser.GameObjects.Components.Origin
|
||||
* @extends Phaser.GameObjects.Components.PostPipeline
|
||||
* @extends Phaser.GameObjects.Components.RenderNode
|
||||
* @extends Phaser.GameObjects.Components.RenderNodes
|
||||
* @extends Phaser.GameObjects.Components.ScrollFactor
|
||||
* @extends Phaser.GameObjects.Components.TextureCrop
|
||||
* @extends Phaser.GameObjects.Components.Tint
|
||||
|
@ -85,7 +86,7 @@ var TileSprite = new Class({
|
|||
Components.Mask,
|
||||
Components.Origin,
|
||||
Components.PostPipeline,
|
||||
Components.RenderNode,
|
||||
Components.RenderNodes,
|
||||
Components.ScrollFactor,
|
||||
Components.TextureCrop,
|
||||
Components.Tint,
|
||||
|
@ -278,10 +279,27 @@ var TileSprite = new Class({
|
|||
this.setPosition(x, y);
|
||||
this.setSize(width, height);
|
||||
this.setOrigin(0.5, 0.5);
|
||||
this.initRenderNodes('TileSprite');
|
||||
this.initRenderNodes(this._defaultRenderNodesMap);
|
||||
this.initPostPipeline(true);
|
||||
},
|
||||
|
||||
/**
|
||||
* The default render nodes for this Game Object.
|
||||
*
|
||||
* @name Phaser.GameObjects.TileSprite#_defaultRenderNodesMap
|
||||
* @type {Map<string, string>}
|
||||
* @private
|
||||
* @webglOnly
|
||||
* @readonly
|
||||
* @since 3.90.0
|
||||
*/
|
||||
_defaultRenderNodesMap: {
|
||||
get: function ()
|
||||
{
|
||||
return DefaultTileSpriteNodes;
|
||||
}
|
||||
},
|
||||
|
||||
// Overrides Game Object method
|
||||
addedToScene: function ()
|
||||
{
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
|
||||
var Clamp = require('../../math/Clamp');
|
||||
var DefaultImageNodes = require('../../renderer/webgl/renderNodes/defaults/DefaultImageNodes');
|
||||
var Class = require('../../utils/Class');
|
||||
var Components = require('../components');
|
||||
var Events = require('../events');
|
||||
|
@ -105,7 +106,7 @@ var VideoRender = require('./VideoRender');
|
|||
* @extends Phaser.GameObjects.Components.Mask
|
||||
* @extends Phaser.GameObjects.Components.Origin
|
||||
* @extends Phaser.GameObjects.Components.PostPipeline
|
||||
* @extends Phaser.GameObjects.Components.RenderNode
|
||||
* @extends Phaser.GameObjects.Components.RenderNodes
|
||||
* @extends Phaser.GameObjects.Components.ScrollFactor
|
||||
* @extends Phaser.GameObjects.Components.TextureCrop
|
||||
* @extends Phaser.GameObjects.Components.Tint
|
||||
|
@ -132,7 +133,7 @@ var Video = new Class({
|
|||
Components.Mask,
|
||||
Components.Origin,
|
||||
Components.PostPipeline,
|
||||
Components.RenderNode,
|
||||
Components.RenderNodes,
|
||||
Components.ScrollFactor,
|
||||
Components.TextureCrop,
|
||||
Components.Tint,
|
||||
|
@ -519,7 +520,7 @@ var Video = new Class({
|
|||
|
||||
this.setPosition(x, y);
|
||||
this.setSize(256, 256);
|
||||
this.initRenderNodes('Image');
|
||||
this.initRenderNodes(this._defaultRenderNodesMap);
|
||||
this.initPostPipeline(true);
|
||||
|
||||
game.events.on(GameEvents.PAUSE, this.globalPause, this);
|
||||
|
@ -538,6 +539,23 @@ var Video = new Class({
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* The default render node map for this Game Object.
|
||||
*
|
||||
* @name Phaser.GameObjects.Video#_defaultRenderNodesMap
|
||||
* @type {Map<string, string>}
|
||||
* @private
|
||||
* @webglOnly
|
||||
* @readonly
|
||||
* @since 3.90.0
|
||||
*/
|
||||
_defaultRenderNodesMap: {
|
||||
get: function ()
|
||||
{
|
||||
return DefaultImageNodes;
|
||||
}
|
||||
},
|
||||
|
||||
// Overrides Game Object method
|
||||
addedToScene: function ()
|
||||
{
|
||||
|
|
|
@ -279,6 +279,7 @@ var ProgramManager = new Class({
|
|||
* @method Phaser.Renderer.WebGL.ProgramManager#getAdditionsByTag
|
||||
* @since 3.90.0
|
||||
* @param {string} tag - The tag to filter by.
|
||||
* @returns {Phaser.Types.Renderer.WebGL.ShaderAdditionConfig[]} The shader additions with the tag.
|
||||
*/
|
||||
getAdditionsByTag: function (tag)
|
||||
{
|
||||
|
@ -292,6 +293,22 @@ var ProgramManager = new Class({
|
|||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the index of a shader addition with the given name.
|
||||
*
|
||||
* @method Phaser.Renderer.WebGL.ProgramManager#getAdditionIndex
|
||||
* @since 3.90.0
|
||||
* @param {string} name - The name to find.
|
||||
* @returns {number} The index of the addition, or `-1` if it was not found.
|
||||
*/
|
||||
getAdditionIndex: function (name)
|
||||
{
|
||||
return this.currentConfig.additions.findIndex(function (addition)
|
||||
{
|
||||
return addition.name === name;
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove a shader addition from the current configuration.
|
||||
*
|
||||
|
@ -307,6 +324,27 @@ var ProgramManager = new Class({
|
|||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Replace a shader addition in the current configuration.
|
||||
*
|
||||
* @method Phaser.Renderer.WebGL.ProgramManager#replaceAddition
|
||||
* @since 3.90.0
|
||||
* @param {string} name - The name of the shader addition to replace.
|
||||
* @param {Phaser.Types.Renderer.WebGL.ShaderAdditionConfig} addition - The new shader addition.
|
||||
*/
|
||||
replaceAddition: function (name, addition)
|
||||
{
|
||||
var index = this.currentConfig.additions.findIndex(function (a)
|
||||
{
|
||||
return a.name === name;
|
||||
});
|
||||
|
||||
if (index !== -1)
|
||||
{
|
||||
this.currentConfig.additions[index] = addition;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Add a feature to the current configuration.
|
||||
*
|
||||
|
|
|
@ -514,6 +514,18 @@ var WebGLRenderer = new Class({
|
|||
*/
|
||||
this.instancedArraysExtension = null;
|
||||
|
||||
/**
|
||||
* If the browser supports the `OES_standard_derivatives` extension,
|
||||
* and the `smoothPixelArt` config option is true,
|
||||
* this property will hold a reference to the glExtension for it.
|
||||
*
|
||||
* @name Phaser.Renderer.WebGL.WebGLRenderer#standardDerivativesExtension
|
||||
* @type {OES_standard_derivatives}
|
||||
* @default null
|
||||
* @since 3.90.0
|
||||
*/
|
||||
this.standardDerivativesExtension = null;
|
||||
|
||||
/**
|
||||
* If the browser supports the `OES_vertex_array_object` extension, this property will hold
|
||||
* a reference to the glExtension for it.
|
||||
|
@ -893,6 +905,12 @@ var WebGLRenderer = new Class({
|
|||
|
||||
_this.vaoExtension = (exts.indexOf(vaoString) > -1) ? gl.getExtension(vaoString) : null;
|
||||
|
||||
if (game.config.smoothPixelArt)
|
||||
{
|
||||
var stdDerivativesString = 'OES_standard_derivatives';
|
||||
|
||||
_this.standardDerivativesExtension = (exts.indexOf(stdDerivativesString) > -1) ? gl.getExtension(stdDerivativesString) : null;
|
||||
}
|
||||
};
|
||||
|
||||
setupExtensions();
|
||||
|
|
|
@ -6,13 +6,21 @@
|
|||
|
||||
var Vector2 = require('../../../math/Vector2');
|
||||
var Class = require('../../../utils/Class');
|
||||
var DeepCopy = require('../../../utils/object/DeepCopy');
|
||||
var Utils = require('../Utils');
|
||||
var ShaderSourceFS = require('../shaders/Multi-frag');
|
||||
var ShaderSourceVS = require('../shaders/Multi-vert');
|
||||
var MakeApplyLighting = require('../shaders/configs/MakeApplyLighting');
|
||||
var MakeApplyTint = require('../shaders/configs/MakeApplyTint');
|
||||
var MakeDefineLights = require('../shaders/configs/MakeDefineLights');
|
||||
var MakeDefineTexCount = require('../shaders/configs/MakeDefineTexCount');
|
||||
var MakeGetNormalFromMap = require('../shaders/configs/MakeGetNormalFromMap');
|
||||
var MakeGetTexCoordOut = require('../shaders/configs/MakeGetTexCoordOut');
|
||||
var MakeGetTexRes = require('../shaders/configs/MakeGetTexRes');
|
||||
var MakeGetTexture = require('../shaders/configs/MakeGetTexture');
|
||||
var MakeOutInverseRotation = require('../shaders/configs/MakeOutInverseRotation');
|
||||
var MakeRotationDatum = require('../shaders/configs/MakeRotationDatum');
|
||||
var MakeSmoothPixelArt = require('../shaders/configs/MakeSmoothPixelArt');
|
||||
var BatchHandler = require('./BatchHandler');
|
||||
|
||||
/**
|
||||
|
@ -32,6 +40,7 @@ var BatchHandlerQuad = new Class({
|
|||
|
||||
initialize: function BatchHandlerQuad (manager, config)
|
||||
{
|
||||
// Placed before super call because the constructor needs it.
|
||||
/**
|
||||
* The current render options to which the batch is built.
|
||||
* These help define the shader.
|
||||
|
@ -42,10 +51,12 @@ var BatchHandlerQuad = new Class({
|
|||
*/
|
||||
this.renderOptions = {
|
||||
multiTexturing: false,
|
||||
texRes: false,
|
||||
lighting: false,
|
||||
selfShadow: false,
|
||||
selfShadowPenumbra: 0,
|
||||
selfShadowThreshold: 0
|
||||
selfShadowThreshold: 0,
|
||||
smoothPixelArt: false
|
||||
};
|
||||
|
||||
BatchHandler.call(this, manager, config, this.defaultConfig);
|
||||
|
@ -57,6 +68,16 @@ var BatchHandlerQuad = new Class({
|
|||
this.manager.renderer.textureUnitIndices
|
||||
);
|
||||
|
||||
/**
|
||||
* The render options currently being built.
|
||||
* These are assigned to `renderOptions` by `applyRenderOptions`.
|
||||
*
|
||||
* @name Phaser.Renderer.WebGL.RenderNodes.BatchHandlerQuad#nextRenderOptions
|
||||
* @type {object}
|
||||
* @since 3.90.0
|
||||
*/
|
||||
this.nextRenderOptions = DeepCopy(this.renderOptions);
|
||||
|
||||
/**
|
||||
* A persistent calculation vector used when processing the lights.
|
||||
*
|
||||
|
@ -84,9 +105,16 @@ var BatchHandlerQuad = new Class({
|
|||
vertexSource: ShaderSourceVS,
|
||||
fragmentSource: ShaderSourceFS,
|
||||
shaderAdditions: [
|
||||
MakeGetTexture(1),
|
||||
MakeGetTexCoordOut(),
|
||||
MakeGetTexRes(true),
|
||||
MakeSmoothPixelArt(true),
|
||||
MakeDefineTexCount(1),
|
||||
MakeGetTexture(),
|
||||
MakeApplyTint(),
|
||||
MakeDefineLights(true),
|
||||
MakeRotationDatum(true),
|
||||
MakeOutInverseRotation(true),
|
||||
MakeGetNormalFromMap(true),
|
||||
MakeApplyLighting(true)
|
||||
],
|
||||
vertexBufferLayout: {
|
||||
|
@ -200,16 +228,14 @@ var BatchHandlerQuad = new Class({
|
|||
if (this.renderOptions.multiTexturing)
|
||||
{
|
||||
var programManager = this.programManager;
|
||||
var textureAdditions = programManager.getAdditionsByTag('TEXTURE');
|
||||
while (textureAdditions.length > 0)
|
||||
var textureAddition = programManager.getAdditionsByTag('TEXTURE')[0];
|
||||
if (textureAddition)
|
||||
{
|
||||
var textureAddition = textureAdditions.pop();
|
||||
programManager.removeAddition(textureAddition.name);
|
||||
programManager.replaceAddition(
|
||||
textureAddition.name,
|
||||
MakeGetTexture(this.maxTexturesPerBatch)
|
||||
);
|
||||
}
|
||||
programManager.addAddition(
|
||||
MakeGetTexture(this.maxTexturesPerBatch),
|
||||
0
|
||||
);
|
||||
}
|
||||
|
||||
this.resize(renderer.width, renderer.height);
|
||||
|
@ -249,111 +275,167 @@ var BatchHandlerQuad = new Class({
|
|||
drawingContext.renderer.projectionMatrix.val
|
||||
);
|
||||
|
||||
// Lighting uniforms.
|
||||
Utils.updateLightingUniforms(
|
||||
renderOptions.lighting,
|
||||
this.manager.renderer,
|
||||
drawingContext,
|
||||
programManager,
|
||||
1,
|
||||
this._lightVector,
|
||||
renderOptions.selfShadow,
|
||||
renderOptions.selfShadowThreshold,
|
||||
renderOptions.selfShadowPenumbra
|
||||
);
|
||||
if (this.renderOptions.lighting)
|
||||
{
|
||||
// Lighting uniforms.
|
||||
Utils.updateLightingUniforms(
|
||||
renderOptions.lighting,
|
||||
this.manager.renderer,
|
||||
drawingContext,
|
||||
programManager,
|
||||
1,
|
||||
this._lightVector,
|
||||
renderOptions.selfShadow,
|
||||
renderOptions.selfShadowThreshold,
|
||||
renderOptions.selfShadowPenumbra
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Update the texture uniforms for the current shader program.
|
||||
*
|
||||
* This method is called automatically when the batch is run.
|
||||
*
|
||||
* @method Phaser.Renderer.WebGL.RenderNodes.BatchHandlerQuad#setupTextureUniforms
|
||||
* @since 3.90.0
|
||||
* @param {Phaser.Renderer.WebGL.WebGLTextureWrapper[]} textures - The textures to render.
|
||||
*/
|
||||
setupTextureUniforms: function (textures)
|
||||
{
|
||||
var programManager = this.programManager;
|
||||
|
||||
if (this.renderOptions.multiTexturing)
|
||||
{
|
||||
// In the shader, this is an array of vec2s.
|
||||
// But we must compose it as a flat array,
|
||||
// not an array of arrays.
|
||||
var dims = [];
|
||||
for (var i = 0; i < textures.length; i++)
|
||||
{
|
||||
dims.push(textures[i].width, textures[i].height);
|
||||
}
|
||||
programManager.setUniform(
|
||||
'uMainResolution[0]',
|
||||
dims
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
programManager.setUniform(
|
||||
'uMainResolution[0]',
|
||||
[ textures[0].width, textures[0].height ]
|
||||
);
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* Update the render options for the current shader program.
|
||||
* If the options have changed, the batch is run to apply the changes.
|
||||
*
|
||||
* @method Phaser.Renderer.WebGL.RenderNodes.BatchHandlerQuad#updateRenderOptions
|
||||
* @since 3.90.0
|
||||
* @param {Phaser.Types.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context.
|
||||
* @param {object} renderOptions - The new render options.
|
||||
*/
|
||||
updateRenderOptions: function (drawingContext, renderOptions)
|
||||
updateRenderOptions: function (renderOptions)
|
||||
{
|
||||
var newRenderOptions = this.nextRenderOptions;
|
||||
|
||||
newRenderOptions.multiTexturing = !!renderOptions.multiTexturing && !renderOptions.lighting;
|
||||
newRenderOptions.lighting = !!renderOptions.lighting;
|
||||
newRenderOptions.selfShadow = newRenderOptions.lighting && renderOptions.lighting.selfShadow && renderOptions.lighting.selfShadow.enabled;
|
||||
newRenderOptions.selfShadowPenumbra = newRenderOptions.selfShadow ? renderOptions.lighting.selfShadow.penumbra : 0;
|
||||
newRenderOptions.selfShadowThreshold = newRenderOptions.selfShadow ? renderOptions.lighting.selfShadow.diffuseFlatThreshold : 0;
|
||||
newRenderOptions.smoothPixelArt = !!renderOptions.smoothPixelArt;
|
||||
newRenderOptions.texRes = newRenderOptions.smoothPixelArt;
|
||||
},
|
||||
|
||||
/**
|
||||
* Check `renderOptions` against `nextRenderOptions`.
|
||||
* If they differ, run the batch, and apply the new options.
|
||||
*
|
||||
* @method Phaser.Renderer.WebGL.RenderNodes.BatchHandlerQuad#applyRenderOptions
|
||||
* @since 3.90.0
|
||||
* @param {Phaser.Types.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context.
|
||||
*/
|
||||
applyRenderOptions: function (drawingContext)
|
||||
{
|
||||
var renderOptions = this.renderOptions;
|
||||
var nextRenderOptions = this.nextRenderOptions;
|
||||
|
||||
var changed = false;
|
||||
for (var key in nextRenderOptions)
|
||||
{
|
||||
if (nextRenderOptions[key] !== renderOptions[key])
|
||||
{
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (changed)
|
||||
{
|
||||
this.run(drawingContext);
|
||||
this.updateShaderConfig();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Update the shader configuration based on render options.
|
||||
* This is called automatically when the render options change.
|
||||
*
|
||||
* @method Phaser.Renderer.WebGL.RenderNodes.BatchHandlerQuad#updateShaderConfig
|
||||
* @since 3.90.0
|
||||
*/
|
||||
updateShaderConfig: function ()
|
||||
{
|
||||
var programManager = this.programManager;
|
||||
var oldRenderOptions = this.renderOptions;
|
||||
var newRenderOptions = {
|
||||
multiTexturing: false,
|
||||
lighting: false,
|
||||
selfShadow: false,
|
||||
selfShadowPenumbra: 0,
|
||||
selfShadowThreshold: 0
|
||||
};
|
||||
var newRenderOptions = this.nextRenderOptions;
|
||||
var i;
|
||||
|
||||
// Parse shader-relevant render options.
|
||||
if (renderOptions)
|
||||
if (oldRenderOptions.multiTexturing !== newRenderOptions.multiTexturing)
|
||||
{
|
||||
// Multitexturing is disabled if other textures are in use.
|
||||
newRenderOptions.multiTexturing = !!renderOptions.multiTexturing && !renderOptions.lighting;
|
||||
var multiTexturing = newRenderOptions.multiTexturing;
|
||||
oldRenderOptions.multiTexturing = multiTexturing;
|
||||
|
||||
newRenderOptions.lighting = !!renderOptions.lighting;
|
||||
|
||||
if (renderOptions.lighting && renderOptions.lighting.selfShadow && renderOptions.lighting.selfShadow.enabled)
|
||||
var texCountAddition = programManager.getAdditionsByTag('TexCount')[0];
|
||||
if (texCountAddition)
|
||||
{
|
||||
newRenderOptions.selfShadow = true;
|
||||
newRenderOptions.selfShadowPenumbra = renderOptions.lighting.selfShadow.penumbra;
|
||||
newRenderOptions.selfShadowThreshold = renderOptions.lighting.selfShadow.diffuseFlatThreshold;
|
||||
programManager.replaceAddition(
|
||||
texCountAddition.name,
|
||||
MakeDefineTexCount(multiTexturing ? this.maxTexturesPerBatch : 1)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Check for changes.
|
||||
var updateTexturing = newRenderOptions.multiTexturing !== oldRenderOptions.multiTexturing;
|
||||
var updateLighting = newRenderOptions.lighting !== oldRenderOptions.lighting;
|
||||
var updateSelfShadow = newRenderOptions.selfShadow !== oldRenderOptions.selfShadow;
|
||||
var updateSelfShadowPenumbra = newRenderOptions.selfShadowPenumbra !== oldRenderOptions.selfShadowPenumbra;
|
||||
var updateSelfShadowThreshold = newRenderOptions.selfShadowThreshold !== oldRenderOptions.selfShadowThreshold;
|
||||
|
||||
// Run the batch if the shader has changed.
|
||||
if (updateTexturing || updateLighting || updateSelfShadow || updateSelfShadowPenumbra || updateSelfShadowThreshold)
|
||||
if (oldRenderOptions.lighting !== newRenderOptions.lighting)
|
||||
{
|
||||
this.run(drawingContext);
|
||||
}
|
||||
var lighting = newRenderOptions.lighting;
|
||||
oldRenderOptions.lighting = lighting;
|
||||
|
||||
// Cache new render options.
|
||||
this.renderOptions = newRenderOptions;
|
||||
|
||||
// Update shader program configuration.
|
||||
if (updateTexturing)
|
||||
{
|
||||
var texturingAddition = programManager.getAdditionsByTag('TEXTURE')[0];
|
||||
if (texturingAddition)
|
||||
var lightingAdditions = programManager.getAdditionsByTag('LIGHTING');
|
||||
for (i = 0; i < lightingAdditions.length; i++)
|
||||
{
|
||||
programManager.removeAddition(texturingAddition.name);
|
||||
|
||||
var lightingAddition = lightingAdditions[i];
|
||||
lightingAddition.disable = !lighting;
|
||||
}
|
||||
var texCount = newRenderOptions.multiTexturing ? this.maxTexturesPerBatch : 1;
|
||||
programManager.addAddition(
|
||||
MakeGetTexture(texCount),
|
||||
0
|
||||
);
|
||||
}
|
||||
|
||||
if (updateLighting)
|
||||
{
|
||||
var lightingAddition = programManager.getAddition('LIGHTING');
|
||||
if (lightingAddition)
|
||||
if (lighting)
|
||||
{
|
||||
lightingAddition.disable = !newRenderOptions.lighting;
|
||||
if (newRenderOptions.lighting)
|
||||
var defineLightsAddition = programManager.getAddition('DefineLights');
|
||||
if (defineLightsAddition)
|
||||
{
|
||||
lightingAddition.additions.fragmentDefine = '#define LIGHT_COUNT ' + this.manager.renderer.config.maxLights;
|
||||
defineLightsAddition.additions.fragmentDefine = '#define LIGHT_COUNT ' + this.manager.renderer.config.maxLights;
|
||||
}
|
||||
}
|
||||
|
||||
var rotationAddition = programManager.getAddition('RotDatum');
|
||||
if (rotationAddition)
|
||||
{
|
||||
rotationAddition.disable = !newRenderOptions.lighting;
|
||||
}
|
||||
}
|
||||
|
||||
if (updateSelfShadow)
|
||||
if (oldRenderOptions.selfShadow !== newRenderOptions.selfShadow)
|
||||
{
|
||||
if (newRenderOptions.selfShadow)
|
||||
var selfShadow = newRenderOptions.selfShadow;
|
||||
oldRenderOptions.selfShadow = selfShadow;
|
||||
|
||||
if (selfShadow)
|
||||
{
|
||||
programManager.addFeature('SELFSHADOW');
|
||||
}
|
||||
|
@ -362,6 +444,33 @@ var BatchHandlerQuad = new Class({
|
|||
programManager.removeFeature('SELFSHADOW');
|
||||
}
|
||||
}
|
||||
|
||||
oldRenderOptions.selfShadowPenumbra = newRenderOptions.selfShadowPenumbra;
|
||||
oldRenderOptions.selfShadowThreshold = newRenderOptions.selfShadowThreshold;
|
||||
|
||||
if (oldRenderOptions.smoothPixelArt !== newRenderOptions.smoothPixelArt)
|
||||
{
|
||||
var smoothPixelArt = newRenderOptions.smoothPixelArt;
|
||||
oldRenderOptions.smoothPixelArt = smoothPixelArt;
|
||||
|
||||
var smoothPixelArtAddition = programManager.getAddition('SmoothPixelArt');
|
||||
if (smoothPixelArtAddition)
|
||||
{
|
||||
smoothPixelArtAddition.disable = !smoothPixelArt;
|
||||
}
|
||||
}
|
||||
|
||||
if (oldRenderOptions.texRes !== newRenderOptions.texRes)
|
||||
{
|
||||
var texRes = newRenderOptions.texRes;
|
||||
oldRenderOptions.texRes = texRes;
|
||||
|
||||
var texResAddition = programManager.getAddition('GetTexRes');
|
||||
if (texResAddition)
|
||||
{
|
||||
texResAddition.disable = !texRes;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -405,6 +514,13 @@ var BatchHandlerQuad = new Class({
|
|||
for (var i = 0; i < subBatches; i++)
|
||||
{
|
||||
var entry = this.batchEntries[i];
|
||||
|
||||
if (this.renderOptions.texRes)
|
||||
{
|
||||
this.setupTextureUniforms(entry.texture);
|
||||
programManager.applyUniforms(program);
|
||||
}
|
||||
|
||||
renderer.drawElements(
|
||||
drawingContext,
|
||||
entry.texture,
|
||||
|
@ -455,7 +571,7 @@ var BatchHandlerQuad = new Class({
|
|||
* @param {number} tintBL - The bottom-left tint color.
|
||||
* @param {number} tintTR - The top-right tint color.
|
||||
* @param {number} tintBR - The bottom-right tint color.
|
||||
* @param {object} [renderOptions] - Optional render features.
|
||||
* @param {object} renderOptions - Optional render features.
|
||||
* @param {boolean} [renderOptions.multiTexturing] - Whether to use multi-texturing.
|
||||
* @param {object} [renderOptions.lighting] - How to treat lighting. If this object is defined, lighting will be activated, and multi-texturing disabled.
|
||||
* @param {Phaser.Renderer.WebGL.WebGLTextureWrapper} renderOptions.lighting.normalGLTexture - The normal map texture to render.
|
||||
|
@ -464,6 +580,7 @@ var BatchHandlerQuad = new Class({
|
|||
* @param {boolean} renderOptions.lighting.selfShadow.enabled - Whether to use self-shadowing.
|
||||
* @param {number} renderOptions.lighting.selfShadow.penumbra - Self-shadowing penumbra strength.
|
||||
* @param {number} renderOptions.lighting.selfShadow.diffuseFlatThreshold - Self-shadowing texture brightness equivalent to a flat surface.
|
||||
* @param {boolean} [renderOptions.smoothPixelArt] - Whether to use the smooth pixel art algorithm.
|
||||
*/
|
||||
batch: function (
|
||||
currentContext,
|
||||
|
@ -485,7 +602,8 @@ var BatchHandlerQuad = new Class({
|
|||
}
|
||||
|
||||
// Check render options and run the batch if they differ.
|
||||
this.updateRenderOptions(currentContext, renderOptions);
|
||||
this.updateRenderOptions(renderOptions);
|
||||
this.applyRenderOptions(currentContext);
|
||||
|
||||
// Process textures and get relevant data.
|
||||
var textureDatum = this.batchTextures(glTexture, renderOptions);
|
||||
|
|
|
@ -8,6 +8,10 @@ var Class = require('../../../utils/Class');
|
|||
var ShaderSourceFS = require('../shaders/Multi-frag');
|
||||
var ShaderSourceVS = require('../shaders/Multi-vert');
|
||||
var MakeApplyTint = require('../shaders/configs/MakeApplyTint');
|
||||
var MakeDefineTexCount = require('../shaders/configs/MakeDefineTexCount');
|
||||
var MakeGetTexCoordOut = require('../shaders/configs/MakeGetTexCoordOut');
|
||||
var MakeGetTexRes = require('../shaders/configs/MakeGetTexRes');
|
||||
var MakeSmoothPixelArt = require('../shaders/configs/MakeSmoothPixelArt');
|
||||
var MakeGetTexture = require('../shaders/configs/MakeGetTexture');
|
||||
var Utils = require('../Utils');
|
||||
var BatchHandlerQuad = require('./BatchHandlerQuad');
|
||||
|
@ -57,7 +61,11 @@ var BatchHandlerStrip = new Class({
|
|||
vertexSource: ShaderSourceVS,
|
||||
fragmentSource: ShaderSourceFS,
|
||||
shaderAdditions: [
|
||||
MakeGetTexture(1),
|
||||
MakeGetTexCoordOut(),
|
||||
MakeGetTexRes(true),
|
||||
MakeSmoothPixelArt(true),
|
||||
MakeDefineTexCount(1),
|
||||
MakeGetTexture(),
|
||||
MakeApplyTint()
|
||||
],
|
||||
vertexBufferLayout: {
|
||||
|
@ -131,8 +139,11 @@ var BatchHandlerStrip = new Class({
|
|||
* @param {number} alpha - The overall alpha value of the strip.
|
||||
* @param {number} tintFill - Whether to tint the fill color.
|
||||
* @param {function} [debugCallback] - The debug callback, called with an array consisting of alternating x,y values of the transformed vertices.
|
||||
* @param {object} renderOptions - Optional render features.
|
||||
* @param {boolean} [renderOptions.multiTexturing] - Whether to use multi-texturing. This should always be false for ropes.
|
||||
* @param {boolean} [renderOptions.smoothPixelArt] - Whether to use the smooth pixel art algorithm.
|
||||
*/
|
||||
batch: function (drawingContext, src, calcMatrix, glTexture, vertices, uv, colors, alphas, alpha, tintFill, debugCallback)
|
||||
batch: function (drawingContext, src, calcMatrix, glTexture, vertices, uv, colors, alphas, alpha, tintFill, debugCallback, renderOptions)
|
||||
{
|
||||
if (this.instanceCount === 0)
|
||||
{
|
||||
|
@ -154,6 +165,10 @@ var BatchHandlerStrip = new Class({
|
|||
// Now the batch is empty.
|
||||
}
|
||||
|
||||
// Check render options and run the batch if they differ.
|
||||
this.updateRenderOptions(renderOptions);
|
||||
this.applyRenderOptions(drawingContext);
|
||||
|
||||
// Process textures and get relevant data.
|
||||
var textureDatum = this.batchTextures(glTexture);
|
||||
|
||||
|
|
|
@ -9,14 +9,25 @@ var ShaderSourceFS = require('../shaders/Multi-frag');
|
|||
var ShaderSourceVS = require('../shaders/Multi-vert');
|
||||
var MakeApplyLighting = require('../shaders/configs/MakeApplyLighting');
|
||||
var MakeApplyTint = require('../shaders/configs/MakeApplyTint');
|
||||
var MakeDefineLights = require('../shaders/configs/MakeDefineLights');
|
||||
var MakeDefineTexCount = require('../shaders/configs/MakeDefineTexCount');
|
||||
var MakeGetNormalFromMap = require('../shaders/configs/MakeGetNormalFromMap');
|
||||
var MakeGetTexCoordOut = require('../shaders/configs/MakeGetTexCoordOut');
|
||||
var MakeGetTexRes = require('../shaders/configs/MakeGetTexRes');
|
||||
var MakeGetTexture = require('../shaders/configs/MakeGetTexture');
|
||||
var MakeOutFrame = require('../shaders/configs/MakeOutFrame');
|
||||
var MakeOutInverseRotation = require('../shaders/configs/MakeOutInverseRotation');
|
||||
var MakeRotationDatum = require('../shaders/configs/MakeRotationDatum');
|
||||
var MakeTileSpriteWrap = require('../shaders/configs/MakeTileSpriteWrap');
|
||||
var MakeSmoothPixelArt = require('../shaders/configs/MakeSmoothPixelArt');
|
||||
var MakeTexCoordFrameClamp = require('../shaders/configs/MakeTexCoordFrameClamp');
|
||||
var MakeTexCoordFrameWrap = require('../shaders/configs/MakeTexCoordFrameWrap');
|
||||
var BatchHandlerQuad = require('./BatchHandlerQuad');
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* This RenderNode handles batch rendering of TileSprites.
|
||||
* This RenderNode handles batch rendering of TileSprites and Tiles.
|
||||
* It supplies shaders with knowledge of the frame and texture data,
|
||||
* which can be used to handle texture borders more intelligently.
|
||||
*
|
||||
* @class BatchHandlerTileSprite
|
||||
* @memberof Phaser.Renderer.WebGL.RenderNodes
|
||||
|
@ -42,10 +53,19 @@ var BatchHandlerTileSprite = new Class({
|
|||
vertexSource: ShaderSourceVS,
|
||||
fragmentSource: ShaderSourceFS,
|
||||
shaderAdditions: [
|
||||
MakeGetTexture(1),
|
||||
MakeTileSpriteWrap(),
|
||||
MakeOutFrame(),
|
||||
MakeGetTexCoordOut(),
|
||||
MakeGetTexRes(true),
|
||||
MakeTexCoordFrameWrap(true),
|
||||
MakeTexCoordFrameClamp(true),
|
||||
MakeSmoothPixelArt(true),
|
||||
MakeDefineTexCount(1),
|
||||
MakeGetTexture(),
|
||||
MakeApplyTint(),
|
||||
MakeDefineLights(true),
|
||||
MakeRotationDatum(true),
|
||||
MakeOutInverseRotation(true),
|
||||
MakeGetNormalFromMap(true),
|
||||
MakeApplyLighting(true)
|
||||
],
|
||||
vertexBufferLayout: {
|
||||
|
@ -79,12 +99,52 @@ var BatchHandlerTileSprite = new Class({
|
|||
}
|
||||
},
|
||||
|
||||
updateRenderOptions: function (renderOptions)
|
||||
{
|
||||
BatchHandlerQuad.prototype.updateRenderOptions.call(this, renderOptions);
|
||||
|
||||
var newRenderOptions = this.nextRenderOptions;
|
||||
|
||||
newRenderOptions.clampFrame = !!renderOptions.clampFrame;
|
||||
newRenderOptions.wrapFrame = !!renderOptions.wrapFrame;
|
||||
|
||||
// Enable texture resolution data if not already available.
|
||||
newRenderOptions.texRes = newRenderOptions.clampFrame || newRenderOptions.texRes;
|
||||
},
|
||||
|
||||
updateShaderConfig: function ()
|
||||
{
|
||||
BatchHandlerQuad.prototype.updateShaderConfig.call(this);
|
||||
|
||||
var programManager = this.programManager;
|
||||
var oldRenderOptions = this.renderOptions;
|
||||
var newRenderOptions = this.nextRenderOptions;
|
||||
|
||||
if (newRenderOptions.clampFrame !== oldRenderOptions.clampFrame)
|
||||
{
|
||||
var clampFrame = newRenderOptions.clampFrame;
|
||||
oldRenderOptions.clampFrame = clampFrame;
|
||||
|
||||
var clampAddition = programManager.getAddition('TexCoordFrameClamp');
|
||||
clampAddition.disable = !newRenderOptions.clampFrame;
|
||||
}
|
||||
|
||||
if (newRenderOptions.wrapFrame !== oldRenderOptions.wrapFrame)
|
||||
{
|
||||
var wrapFrame = newRenderOptions.wrapFrame;
|
||||
oldRenderOptions.wrapFrame = wrapFrame;
|
||||
|
||||
var wrapAddition = programManager.getAddition('TexCoordFrameWrap');
|
||||
wrapAddition.disable = !wrapFrame;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Add a TileSprite to the batch.
|
||||
* Add a quad to the batch.
|
||||
*
|
||||
* @method Phaser.Renderer.WebGL.RenderNodes.BatchHandlerTileSprite#batch
|
||||
* @since 3.90.0
|
||||
* @param {Phaser.Renderer.WebGL.DrawingContext} currentContext - The current drawing context.
|
||||
* @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context.
|
||||
* @param {Phaser.Renderer.WebGL.WebGLTextureWrapper} glTexture - The texture to render.
|
||||
* @param {number} x0 - The x-coordinate of the top-left corner.
|
||||
* @param {number} y0 - The y-coordinate of the top-left corner.
|
||||
|
@ -111,7 +171,7 @@ var BatchHandlerTileSprite = new Class({
|
|||
* @param {number} tintBL - The tint color for the bottom-left corner.
|
||||
* @param {number} tintTR - The tint color for the top-right corner.
|
||||
* @param {number} tintBR - The tint color for the bottom-right corner.
|
||||
* @param {object} [renderOptions] - Optional render features.
|
||||
* @param {object} renderOptions - Optional render features.
|
||||
* @param {boolean} [renderOptions.multiTexturing] - Whether to use multi-texturing.
|
||||
* @param {object} [renderOptions.lighting] - How to treat lighting. If this object is defined, lighting will be activated, and multi-texturing disabled.
|
||||
* @param {Phaser.Renderer.WebGL.WebGLTextureWrapper} renderOptions.lighting.normalGLTexture - The normal map texture to render.
|
||||
|
@ -120,9 +180,12 @@ var BatchHandlerTileSprite = new Class({
|
|||
* @param {boolean} renderOptions.lighting.selfShadow.enabled - Whether to use self-shadowing.
|
||||
* @param {number} renderOptions.lighting.selfShadow.penumbra - Self-shadowing penumbra strength.
|
||||
* @param {number} renderOptions.lighting.selfShadow.diffuseFlatThreshold - Self-shadowing texture brightness equivalent to a flat surface.
|
||||
* @param {boolean} [renderOptions.smoothPixelArt] - Whether to use the smooth pixel art algorithm.
|
||||
* @param {boolean} [renderOptions.clampFrame] - Whether to clamp the texture frame. This prevents bleeding due to linear filtering. It is mostly useful for tiles.
|
||||
* @param {boolean} [renderOptions.wrapFrame] - Whether to wrap the texture frame. This is necessary for TileSprites.
|
||||
*/
|
||||
batch: function (
|
||||
currentContext,
|
||||
drawingContext,
|
||||
glTexture,
|
||||
x0, y0, x1, y1, x2, y2, x3, y3,
|
||||
texX, texY, texWidth, texHeight,
|
||||
|
@ -134,11 +197,12 @@ var BatchHandlerTileSprite = new Class({
|
|||
{
|
||||
if (this.instanceCount === 0)
|
||||
{
|
||||
this.manager.setCurrentBatchNode(this, currentContext);
|
||||
this.manager.setCurrentBatchNode(this, drawingContext);
|
||||
}
|
||||
|
||||
// Check render options and run the batch if they differ.
|
||||
this.updateRenderOptions(currentContext, renderOptions);
|
||||
this.updateRenderOptions(renderOptions);
|
||||
this.applyRenderOptions(drawingContext);
|
||||
|
||||
// Process textures and get relevant data.
|
||||
var textureDatum = this.batchTextures(glTexture, renderOptions);
|
||||
|
@ -209,7 +273,7 @@ var BatchHandlerTileSprite = new Class({
|
|||
// This guarantees that none of the arrays are full above.
|
||||
if (this.instanceCount === this.instancesPerBatch)
|
||||
{
|
||||
this.run(currentContext);
|
||||
this.run(drawingContext);
|
||||
|
||||
// Now the batch is empty.
|
||||
}
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
var Vector2 = require('../../../math/Vector2');
|
||||
var Class = require('../../../utils/Class');
|
||||
var MakeApplyLighting = require('../shaders/configs/MakeApplyLighting');
|
||||
var MakeDefineLights = require('../shaders/configs/MakeDefineLights');
|
||||
var MakeFlatNormal = require('../shaders/configs/MakeFlatNormal');
|
||||
var ShaderSourceFS = require('../shaders/Flat-frag');
|
||||
var ShaderSourceVS = require('../shaders/Flat-vert');
|
||||
var Utils = require('../Utils');
|
||||
|
@ -73,6 +75,18 @@ var BatchHandlerTriFlat = new Class({
|
|||
this.renderOptions = {
|
||||
lighting: false
|
||||
};
|
||||
|
||||
/**
|
||||
* The render options currently being built.
|
||||
* These are assigned to `renderOptions` by `applyRenderOptions`.
|
||||
*
|
||||
* @name Phaser.Renderer.WebGL.RenderNodes.BatchHandlerTriFlat#nextRenderOptions
|
||||
* @type {object}
|
||||
* @since 3.90.0
|
||||
*/
|
||||
this.nextRenderOptions = {
|
||||
lighting: false
|
||||
};
|
||||
},
|
||||
|
||||
defaultConfig: {
|
||||
|
@ -83,9 +97,10 @@ var BatchHandlerTriFlat = new Class({
|
|||
vertexSource: ShaderSourceVS,
|
||||
fragmentSource: ShaderSourceFS,
|
||||
shaderAdditions: [
|
||||
MakeDefineLights(true),
|
||||
MakeFlatNormal(true),
|
||||
MakeApplyLighting(true)
|
||||
],
|
||||
shaderFeatures: [ 'FLAT_LIGHTING' ],
|
||||
indexBufferDynamic: true,
|
||||
vertexBufferLayout: {
|
||||
usage: 'DYNAMIC_DRAW',
|
||||
|
@ -160,37 +175,58 @@ var BatchHandlerTriFlat = new Class({
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Update the render options for the current shader program.
|
||||
* If the options have changed, the batch is run to apply the changes.
|
||||
*
|
||||
* @method Phaser.Renderer.WebGL.RenderNodes.BatchHandlerTriFlat#updateRenderOptions
|
||||
* @since 3.90.0
|
||||
* @param {Phaser.Types.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context.
|
||||
* @param {boolean} lighting - Should this batch use lighting?
|
||||
*/
|
||||
updateRenderOptions: function (drawingContext, lighting)
|
||||
updateRenderOptions: function (lighting)
|
||||
{
|
||||
var newRenderOptions = this.nextRenderOptions;
|
||||
|
||||
newRenderOptions.lighting = lighting;
|
||||
},
|
||||
|
||||
applyRenderOptions: function (drawingContext)
|
||||
{
|
||||
var renderOptions = this.renderOptions;
|
||||
var nextRenderOptions = this.nextRenderOptions;
|
||||
|
||||
var changed = false;
|
||||
for (var key in nextRenderOptions)
|
||||
{
|
||||
if (nextRenderOptions[key] !== renderOptions[key])
|
||||
{
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (changed)
|
||||
{
|
||||
this.run(drawingContext);
|
||||
this.updateShaderConfig();
|
||||
}
|
||||
},
|
||||
|
||||
updateShaderConfig: function ()
|
||||
{
|
||||
var programManager = this.programManager;
|
||||
var renderOptions = this.renderOptions;
|
||||
var updateLighting = this.renderOptions.lighting !== lighting;
|
||||
var nextRenderOptions = this.nextRenderOptions;
|
||||
|
||||
if (updateLighting)
|
||||
if (renderOptions.lighting !== nextRenderOptions.lighting)
|
||||
{
|
||||
this.run(drawingContext);
|
||||
}
|
||||
|
||||
renderOptions.lighting = lighting;
|
||||
|
||||
if (updateLighting)
|
||||
{
|
||||
var lightingAddition = programManager.getAddition('LIGHTING');
|
||||
if (lightingAddition)
|
||||
var lighting = nextRenderOptions.lighting;
|
||||
renderOptions.lighting = lighting;
|
||||
|
||||
var lightingAdditions = programManager.getAdditionsByTag('LIGHTING');
|
||||
for (var i = 0; i < lightingAdditions.length; i++)
|
||||
{
|
||||
lightingAddition.disable = !lighting;
|
||||
if (lighting)
|
||||
var addition = lightingAdditions[i];
|
||||
addition.disable = !lighting;
|
||||
}
|
||||
|
||||
if (lighting)
|
||||
{
|
||||
var defineLightsAddition = programManager.getAddition('DefineLights');
|
||||
if (defineLightsAddition)
|
||||
{
|
||||
lightingAddition.additions.fragmentDefine = '#define LIGHT_COUNT ' + this.manager.renderer.config.maxLights;
|
||||
defineLightsAddition.additions.fragmentDefine = '#define LIGHT_COUNT ' + this.manager.renderer.config.maxLights;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -277,7 +313,8 @@ var BatchHandlerTriFlat = new Class({
|
|||
}
|
||||
|
||||
// Check render options and run the batch if they differ.
|
||||
this.updateRenderOptions(currentContext, lighting);
|
||||
this.updateRenderOptions(lighting);
|
||||
this.applyRenderOptions(currentContext);
|
||||
|
||||
var passID = 0;
|
||||
var instanceCompletion = 0;
|
||||
|
|
|
@ -8,17 +8,6 @@ var EventEmitter = require('eventemitter3');
|
|||
var Class = require('../../../utils/Class');
|
||||
var Events = require('../../events');
|
||||
|
||||
var DefaultBitmapTextNodes = require('./defaults/DefaultBitmapTextNodes');
|
||||
var DefaultBlitterNodes = require('./defaults/DefaultBlitterNodes');
|
||||
var DefaultGraphicsNodes = require('./defaults/DefaultGraphicsNodes');
|
||||
var DefaultImageNodes = require('./defaults/DefaultImageNodes');
|
||||
var DefaultNineSliceNodes = require('./defaults/DefaultNineSliceNodes');
|
||||
var DefaultParticleEmitterNodes = require('./defaults/DefaultParticleEmitterNodes');
|
||||
var DefaultPointLightNodes = require('./defaults/DefaultPointLightNodes');
|
||||
var DefaultRopeNodes = require('./defaults/DefaultRopeNodes');
|
||||
var DefaultTilemapLayerNodes = require('./defaults/DefaultTilemapLayerNodes');
|
||||
var DefaultTileSpriteNodes = require('./defaults/DefaultTileSpriteNodes');
|
||||
|
||||
var BatchHandlerPointLight = require('./BatchHandlerPointLight');
|
||||
var BatchHandlerQuad = require('./BatchHandlerQuad');
|
||||
var BatchHandlerStrip = require('./BatchHandlerStrip');
|
||||
|
@ -34,6 +23,8 @@ var ListCompositor = require('./ListCompositor');
|
|||
var RebindContext = require('./RebindContext');
|
||||
var StrokePath = require('./StrokePath');
|
||||
var SubmitterQuad = require('./submitter/SubmitterQuad');
|
||||
var SubmitterTile = require('./submitter/SubmitterTile');
|
||||
var SubmitterTilemapGPULayer = require('./submitter/SubmitterTilemapGPULayer');
|
||||
var SubmitterTileSprite = require('./submitter/SubmitterTileSprite');
|
||||
var TexturerImage = require('./texturer/TexturerImage');
|
||||
var TexturerTileSprite = require('./texturer/TexturerTileSprite');
|
||||
|
@ -96,28 +87,6 @@ var RenderNodeManager = new Class({
|
|||
*/
|
||||
this.maxParallelTextureUnits = (game.config.autoMobilePipeline && !game.device.os.desktop) ? 1 : renderer.maxTextures;
|
||||
|
||||
/**
|
||||
* The default render nodes for game objects.
|
||||
* These maps are requested when a game object is created,
|
||||
* and are used to assign default render nodes to the game object.
|
||||
*
|
||||
* @name Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager#defaultRenderNodes
|
||||
* @type {object}
|
||||
* @since 3.90.0
|
||||
*/
|
||||
this.defaultRenderNodes = {
|
||||
BitmapText: DefaultBitmapTextNodes,
|
||||
Blitter: DefaultBlitterNodes,
|
||||
Graphics: DefaultGraphicsNodes,
|
||||
Image: DefaultImageNodes,
|
||||
NineSlice: DefaultNineSliceNodes,
|
||||
ParticleEmitter: DefaultParticleEmitterNodes,
|
||||
PointLight: DefaultPointLightNodes,
|
||||
Rope: DefaultRopeNodes,
|
||||
TilemapLayer: DefaultTilemapLayerNodes,
|
||||
TileSprite: DefaultTileSpriteNodes
|
||||
};
|
||||
|
||||
/**
|
||||
* Nodes available for use. This is an internal object,
|
||||
* where the keys are the names of the nodes.
|
||||
|
@ -162,6 +131,8 @@ var RenderNodeManager = new Class({
|
|||
RebindContext: RebindContext,
|
||||
StrokePath: StrokePath,
|
||||
SubmitterQuad: SubmitterQuad,
|
||||
SubmitterTile: SubmitterTile,
|
||||
SubmitterTilemapGPULayer: SubmitterTilemapGPULayer,
|
||||
SubmitterTileSprite: SubmitterTileSprite,
|
||||
TexturerImage: TexturerImage,
|
||||
TexturerTileSprite: TexturerTileSprite,
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
/**
|
||||
* @author Benjamin D. Richards <benjamindrichards@gmail.com>
|
||||
* @copyright 2013-2024 Phaser Studio Inc.
|
||||
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
||||
*/
|
||||
|
||||
var Map = require('../../../../structs/Map');
|
||||
|
||||
var DefaultImageNodes = new Map([
|
||||
[ 'Submitter', 'SubmitterTilemapGPULayer' ]
|
||||
]);
|
||||
|
||||
module.exports = DefaultImageNodes;
|
|
@ -7,8 +7,8 @@
|
|||
var Map = require('../../../../structs/Map');
|
||||
|
||||
var DefaultTilemapLayerNodes = new Map([
|
||||
[ 'Submitter', 'SubmitterQuad' ],
|
||||
[ 'BatchHandler', 'BatchHandlerQuad' ],
|
||||
[ 'Submitter', 'SubmitterTile' ],
|
||||
[ 'BatchHandler', 'BatchHandlerTileSprite' ],
|
||||
[ 'Transformer', 'TransformerTile' ]
|
||||
]);
|
||||
|
||||
|
|
|
@ -26,6 +26,8 @@ var RenderNodes = {
|
|||
RenderNode: require('./RenderNode'),
|
||||
StrokePath: require('./StrokePath'),
|
||||
SubmitterQuad: require('./submitter/SubmitterQuad'),
|
||||
SubmitterTile: require('./submitter/SubmitterTile'),
|
||||
SubmitterTilemapGPULayer: require('./submitter/SubmitterTilemapGPULayer'),
|
||||
SubmitterTileSprite: require('./submitter/SubmitterTileSprite'),
|
||||
TexturerImage: require('./texturer/TexturerImage'),
|
||||
TexturerTileSprite: require('./texturer/TexturerTileSprite'),
|
||||
|
|
|
@ -62,7 +62,8 @@ var SubmitterQuad = new Class({
|
|||
*/
|
||||
this._renderOptions = {
|
||||
multiTexturing: true,
|
||||
lighting: null
|
||||
lighting: null,
|
||||
smoothPixelArt: null
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -199,29 +200,39 @@ var SubmitterQuad = new Class({
|
|||
|
||||
setRenderOptions: function (gameObject, normalMap, normalMapRotation)
|
||||
{
|
||||
var baseTexture, sourceIndex;
|
||||
if (gameObject.displayTexture)
|
||||
{
|
||||
baseTexture = gameObject.displayTexture;
|
||||
sourceIndex = gameObject.displayFrame.sourceIndex;
|
||||
}
|
||||
else if (gameObject.texture)
|
||||
{
|
||||
baseTexture = gameObject.texture;
|
||||
sourceIndex = gameObject.frame.sourceIndex;
|
||||
}
|
||||
else if (gameObject.tileset)
|
||||
{
|
||||
if (Array.isArray(gameObject.tileset))
|
||||
{
|
||||
baseTexture = gameObject.tileset[0].image;
|
||||
}
|
||||
else
|
||||
{
|
||||
baseTexture = gameObject.tileset.image;
|
||||
}
|
||||
sourceIndex = 0;
|
||||
}
|
||||
|
||||
|
||||
if (gameObject.lighting)
|
||||
{
|
||||
// Get normal map.
|
||||
if (!normalMap)
|
||||
{
|
||||
if (gameObject.displayTexture)
|
||||
if (baseTexture)
|
||||
{
|
||||
normalMap = gameObject.displayTexture.dataSource[gameObject.displayFrame.sourceIndex];
|
||||
}
|
||||
else if (gameObject.texture)
|
||||
{
|
||||
normalMap = gameObject.texture.dataSource[gameObject.frame.sourceIndex];
|
||||
}
|
||||
else if (gameObject.tileset)
|
||||
{
|
||||
if (Array.isArray(gameObject.tileset))
|
||||
{
|
||||
normalMap = gameObject.tileset[0].image.dataSource[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
normalMap = gameObject.tileset.image.dataSource[0];
|
||||
}
|
||||
normalMap = baseTexture.dataSource[sourceIndex];
|
||||
}
|
||||
}
|
||||
if (!normalMap)
|
||||
|
@ -264,6 +275,18 @@ var SubmitterQuad = new Class({
|
|||
{
|
||||
this._renderOptions.lighting = null;
|
||||
}
|
||||
|
||||
// Get smooth pixel art option.
|
||||
var smoothPixelArt;
|
||||
if (baseTexture && baseTexture.smoothPixelArt !== null)
|
||||
{
|
||||
smoothPixelArt = baseTexture.smoothPixelArt;
|
||||
}
|
||||
else
|
||||
{
|
||||
smoothPixelArt = gameObject.scene.game.config.smoothPixelArt;
|
||||
}
|
||||
this._renderOptions.smoothPixelArt = smoothPixelArt;
|
||||
}
|
||||
});
|
||||
|
||||
|
|
160
src/renderer/webgl/renderNodes/submitter/SubmitterTile.js
Normal file
160
src/renderer/webgl/renderNodes/submitter/SubmitterTile.js
Normal file
|
@ -0,0 +1,160 @@
|
|||
/**
|
||||
* @author Benjamin D. Richards <benjamindrichards@gmail.com>
|
||||
* @copyright 2013-2024 Phaser Studio Inc.
|
||||
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
||||
*/
|
||||
|
||||
var Class = require('../../../../utils/Class');
|
||||
var Utils = require('../../Utils.js');
|
||||
var SubmitterQuad = require('./SubmitterQuad');
|
||||
|
||||
var getTint = Utils.getTintAppendFloatAlpha;
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* The SubmitterTile RenderNode submits data for tiles.
|
||||
*
|
||||
* @class SubmitterTile
|
||||
* @extends Phaser.Renderer.WebGL.RenderNodes.SubmitterQuad
|
||||
* @memberof Phaser.Renderer.WebGL.RenderNodes
|
||||
* @constructor
|
||||
* @since 3.90.0
|
||||
* @param {Phaser.Renderer.WebGL.WebGLRenderer} manager - The WebGLRenderer that owns this Submitter.
|
||||
* @param {object} [config] - The configuration object for this Submitter.
|
||||
* @param {string} [config.name='SubmitterTile'] - The name of this Submitter.
|
||||
* @param {string} [config.role='Submitter'] - The role of this Submitter.
|
||||
* @param {string} [config.batchHandler='BatchHandler'] - The key of the default batch handler node to use for this Submitter. This should correspond to a node which extends `BatchHandlerTile`. It will be derived from the game object whenever the node runs.
|
||||
*/
|
||||
var SubmitterTile = new Class({
|
||||
Extends: SubmitterQuad,
|
||||
|
||||
initialize: function SubmitterTile (manager, config)
|
||||
{
|
||||
SubmitterQuad.call(this, manager, config);
|
||||
|
||||
this._renderOptions.clampFrame = true;
|
||||
},
|
||||
|
||||
/**
|
||||
* The default configuration for this RenderNode.
|
||||
*
|
||||
* @name Phaser.Renderer.WebGL.RenderNodes.SubmitterTile#defaultConfig
|
||||
* @type {object}
|
||||
*/
|
||||
defaultConfig: {
|
||||
name: 'SubmitterTile',
|
||||
role: 'Submitter',
|
||||
batchHandler: 'BatchHandler'
|
||||
},
|
||||
|
||||
/**
|
||||
* Submit data for rendering.
|
||||
*
|
||||
* @method Phaser.Renderer.WebGL.RenderNodes.SubmitterTile#run
|
||||
* @since 3.90.0
|
||||
* @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context.
|
||||
* @param {Phaser.GameObjects.GameObject} gameObject - The GameObject being rendered.
|
||||
* @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - The parent matrix of the GameObject.
|
||||
* @param {object} [element] - The specific element within the game object. This is used for objects that consist of multiple quads.
|
||||
* @param {Phaser.Renderer.WebGL.RenderNodes.TexturerTileSprite|Omit<Phaser.Renderer.WebGL.RenderNodes.TexturerTileSprite, 'run'>} texturerNode - The texturer node used to texture the GameObject. You may pass a texturer node or an object containing equivalent data without a `run` method.
|
||||
* @param {Phaser.Renderer.WebGL.RenderNodes.TransformerTileSprite|{ quad: Float32Array }} transformerNode - The transformer node used to transform the GameObject. You may pass a transformer node or an object with a `quad` property.
|
||||
* @param {Phaser.Renderer.WebGL.RenderNodes.RenderNode|Omit<Phaser.Renderer.WebGL.RenderNodes.RenderNode, 'run'>} [tinterNode] - The tinter node used to tint the GameObject. You may pass a tinter node or an object containing equivalent data without a `run` method. If omitted, no tinting will be used.
|
||||
* @param {Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper} [normalMap] - The normal map texture to use for lighting. If omitted, the normal map texture of the GameObject will be used, or the default normal map texture of the renderer.
|
||||
* @param {number} [normalMapRotation] - The rotation of the normal map texture. If omitted, the rotation of the GameObject will be used.
|
||||
*/
|
||||
run: function (
|
||||
drawingContext,
|
||||
gameObject,
|
||||
parentMatrix,
|
||||
element,
|
||||
texturerNode,
|
||||
transformerNode,
|
||||
tinterNode,
|
||||
normalMap,
|
||||
normalMapRotation
|
||||
)
|
||||
{
|
||||
this.onRunBegin(drawingContext);
|
||||
|
||||
var cameraAlpha = drawingContext.camera.alpha;
|
||||
var tintFill, tintTopLeft, tintBottomLeft, tintTopRight, tintBottomRight;
|
||||
|
||||
if (texturerNode.run)
|
||||
{
|
||||
texturerNode.run(drawingContext, gameObject, element);
|
||||
}
|
||||
if (transformerNode.run)
|
||||
{
|
||||
transformerNode.run(drawingContext, gameObject, parentMatrix, element, texturerNode);
|
||||
}
|
||||
if (tinterNode)
|
||||
{
|
||||
if (tinterNode.run)
|
||||
{
|
||||
tinterNode.run(drawingContext, gameObject, element);
|
||||
}
|
||||
tintFill = tinterNode.tintFill;
|
||||
tintTopLeft = tinterNode.tintTopLeft;
|
||||
tintBottomLeft = tinterNode.tintBottomLeft;
|
||||
tintTopRight = tinterNode.tintTopRight;
|
||||
tintBottomRight = tinterNode.tintBottomRight;
|
||||
}
|
||||
else
|
||||
{
|
||||
tintFill = gameObject.tintFill;
|
||||
var tint = getTint(0xffffffff, cameraAlpha);
|
||||
tintTopLeft = tint;
|
||||
tintBottomLeft = tint;
|
||||
tintTopRight = tint;
|
||||
tintBottomRight = tint;
|
||||
}
|
||||
|
||||
var frame = texturerNode.frame;
|
||||
var quad = transformerNode.quad;
|
||||
var uvSource = texturerNode.uvSource;
|
||||
var u0 = uvSource.u0;
|
||||
var v0 = uvSource.v0;
|
||||
var u1 = uvSource.u1;
|
||||
var v1 = uvSource.v1;
|
||||
|
||||
this.setRenderOptions(gameObject, normalMap, normalMapRotation);
|
||||
|
||||
(
|
||||
gameObject.customRenderNodes[this.batchHandler] ||
|
||||
gameObject.defaultRenderNodes[this.batchHandler]
|
||||
).batch(
|
||||
drawingContext,
|
||||
|
||||
// Use `frame.source.glTexture` instead of `frame.glTexture`
|
||||
// to avoid unnecessary getter function calls.
|
||||
frame.source.glTexture,
|
||||
|
||||
// Transformed quad in order TL, BL, TR, BR:
|
||||
quad[0], quad[1],
|
||||
quad[2], quad[3],
|
||||
quad[6], quad[7],
|
||||
quad[4], quad[5],
|
||||
|
||||
// Texture coordinates in X, Y, Width, Height:
|
||||
u0, v0, u1 - u0, v1 - v0,
|
||||
|
||||
// Frame coordinates in order TL, BL, TR, BR:
|
||||
u0, v0,
|
||||
u0, v1,
|
||||
u1, v0,
|
||||
u1, v1,
|
||||
|
||||
tintFill,
|
||||
|
||||
// Tint colors in order TL, BL, TR, BR:
|
||||
tintTopLeft, tintBottomLeft, tintTopRight, tintBottomRight,
|
||||
|
||||
// Extra render options:
|
||||
this._renderOptions
|
||||
);
|
||||
|
||||
this.onRunEnd(drawingContext);
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = SubmitterTile;
|
|
@ -39,6 +39,8 @@ var SubmitterTileSprite = new Class({
|
|||
initialize: function SubmitterTileSprite (manager, config)
|
||||
{
|
||||
SubmitterQuad.call(this, manager, config);
|
||||
|
||||
this._renderOptions.wrapFrame = true;
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,583 @@
|
|||
/**
|
||||
* @author Benjamin D. Richards <benjamindrichards@gmail.com>
|
||||
* @copyright 2013-2024 Phaser Studio Inc.
|
||||
* @license None
|
||||
*/
|
||||
|
||||
var TransformMatrix = require('../../../../gameobjects/components/TransformMatrix');
|
||||
var Vector2 = require('../../../../math/Vector2');
|
||||
var Class = require('../../../../utils/Class');
|
||||
var Merge = require('../../../../utils/object/Merge');
|
||||
var ProgramManager = require('../../ProgramManager');
|
||||
var MakeAnimLength = require('../../shaders/configs/MakeAnimLength');
|
||||
var MakeApplyLighting = require('../../shaders/configs/MakeApplyLighting');
|
||||
var MakeDefineLights = require('../../shaders/configs/MakeDefineLights');
|
||||
var MakeSampleNormal = require('../../shaders/configs/MakeSampleNormal');
|
||||
var MakeSmoothPixelArt = require('../../shaders/configs/MakeSmoothPixelArt');
|
||||
var ShaderSourceFS = require('../../shaders/TilemapGPULayer-frag');
|
||||
var ShaderSourceVS = require('../../shaders/TilemapGPULayer-vert');
|
||||
var WebGLVertexBufferLayoutWrapper = require('../../wrappers/WebGLVertexBufferLayoutWrapper');
|
||||
var RenderNode = require('../RenderNode');
|
||||
var Utils = require('../../Utils');
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* The SubmitterTilemapGPULayer RenderNode handles rendering of
|
||||
* TilemapGPULayer objects.
|
||||
*
|
||||
* It is a Stand Alone Render, meaning that it does not batch.
|
||||
*
|
||||
* @class SubmitterTilemapGPULayer
|
||||
* @extends Phaser.Renderer.WebGL.RenderNodes.RenderNode
|
||||
* @memberof Phaser.Renderer.WebGL.RenderNodes
|
||||
* @constructor
|
||||
* @since 3.90.0
|
||||
* @param {Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager} manager - The manager that owns this RenderNode.
|
||||
* @param {object} [config] - The configuration object for this handler.
|
||||
* @param {string} [config.name='SubmitterTilemapGPULayer'] - The name of this RenderNode.
|
||||
* @param {string} [config.vertexSource] - The vertex shader source.
|
||||
* @param {string} [config.fragmentSource] - The fragment shader source.
|
||||
*/
|
||||
var SubmitterTilemapGPULayer = new Class({
|
||||
Extends: RenderNode,
|
||||
|
||||
initialize: function SubmitterTilemapGPULayer (manager, config)
|
||||
{
|
||||
var renderer = manager.renderer;
|
||||
var gl = renderer.gl;
|
||||
|
||||
var finalConfig = Merge(config || {}, this.defaultConfig);
|
||||
var name = finalConfig.name;
|
||||
this._completeLayout(finalConfig);
|
||||
|
||||
RenderNode.call(this, name, manager);
|
||||
|
||||
/**
|
||||
* The completed configuration object for this RenderNode.
|
||||
* This is defined by the default configuration and the user-defined configuration object.
|
||||
*
|
||||
* @name Phaser.Renderer.WebGL.RenderNodes.SubmitterTilemapGPULayer#config
|
||||
* @type {object}
|
||||
* @since 3.90.0
|
||||
*/
|
||||
this.config = finalConfig;
|
||||
|
||||
// Ensure that there is no VAO bound, because the following index buffer
|
||||
// will modify any currently bound VAO.
|
||||
renderer.glWrapper.updateVAO({ vao: null });
|
||||
|
||||
/**
|
||||
* The index buffer defining vertex order.
|
||||
*
|
||||
* @name Phaser.Renderer.WebGL.RenderNodes.SubmitterTilemapGPULayer#indexBuffer
|
||||
* @type {Phaser.Renderer.WebGL.Wrappers.WebGLBufferWrapper}
|
||||
* @since 3.90.0
|
||||
*/
|
||||
this.indexBuffer = renderer.createIndexBuffer(
|
||||
new Uint16Array([ 0, 1, 2, 3 ]),
|
||||
gl.STATIC_DRAW
|
||||
);
|
||||
|
||||
/**
|
||||
* The vertex buffer layout for this RenderNode.
|
||||
*
|
||||
* This consists of 4 bytes, 0-3, forming corners of a quad instance.
|
||||
*
|
||||
* @name Phaser.Renderer.WebGL.RenderNodes.SubmitterTilemapGPULayer#vertexBufferLayout
|
||||
* @type {Phaser.Renderer.WebGL.WebGLVertexBufferLayoutWrapper}
|
||||
* @since 3.90.0
|
||||
* @readonly
|
||||
*/
|
||||
this.vertexBufferLayout = new WebGLVertexBufferLayoutWrapper(
|
||||
renderer,
|
||||
finalConfig.vertexBufferLayout,
|
||||
finalConfig.createOwnVertexBuffer ? null : renderer.genericVertexBuffer
|
||||
);
|
||||
|
||||
/**
|
||||
* The program manager used to create and manage shader programs.
|
||||
* This contains shader variants.
|
||||
*
|
||||
* @name Phaser.Renderer.WebGL.RenderNodes.BatchHandler#programManager
|
||||
* @type {Phaser.Renderer.WebGL.ProgramManager}
|
||||
* @since 3.90.0
|
||||
*/
|
||||
this.programManager = new ProgramManager(
|
||||
renderer,
|
||||
this.indexBuffer,
|
||||
[ this.vertexBufferLayout ]
|
||||
);
|
||||
|
||||
// Fill in program configuration from config.
|
||||
this.programManager.setBaseShader(
|
||||
finalConfig.shaderName,
|
||||
finalConfig.vertexSource,
|
||||
finalConfig.fragmentSource
|
||||
);
|
||||
if (finalConfig.shaderAdditions)
|
||||
{
|
||||
for (var i = 0; i < finalConfig.shaderAdditions.length; i++)
|
||||
{
|
||||
var addition = finalConfig.shaderAdditions[i];
|
||||
this.programManager.addAddition(addition);
|
||||
}
|
||||
}
|
||||
if (finalConfig.shaderFeatures)
|
||||
{
|
||||
for (i = 0; i < finalConfig.shaderFeatures.length; i++)
|
||||
{
|
||||
this.programManager.addFeature(finalConfig.shaderFeatures[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The matrix used internally to compute sprite transforms.
|
||||
*
|
||||
* @name Phaser.Renderer.WebGL.RenderNodes.SubmitterTilemapGPULayer#_spriteMatrix
|
||||
* @type {Phaser.GameObjects.Components.TransformMatrix}
|
||||
* @since 3.90.0
|
||||
* @private
|
||||
*/
|
||||
this._spriteMatrix = new TransformMatrix();
|
||||
|
||||
/**
|
||||
* The matrix used internally to compute the final transform.
|
||||
*
|
||||
* @name Phaser.Renderer.WebGL.RenderNodes.SubmitterTilemapGPULayer#_calcMatrix
|
||||
* @type {Phaser.GameObjects.Components.TransformMatrix}
|
||||
* @since 3.90.0
|
||||
* @private
|
||||
*/
|
||||
this._calcMatrix = new TransformMatrix();
|
||||
|
||||
/**
|
||||
* A vector used for temporary calculations.
|
||||
*
|
||||
* @name Phaser.Renderer.WebGL.RenderNodes.SubmitterTilemapGPULayer#_lightVector
|
||||
* @type {Phaser.Math.Vector2}
|
||||
* @since 3.90.0
|
||||
* @private
|
||||
*/
|
||||
this._lightVector = new Vector2();
|
||||
|
||||
/**
|
||||
* The matrix used to store the final quad data for rendering.
|
||||
*
|
||||
* @name Phaser.Renderer.WebGL.RenderNodes.SubmitterTilemapGPULayer#_quad
|
||||
* @type {Float32Array}
|
||||
* @since 3.90.0
|
||||
* @private
|
||||
*/
|
||||
this._quad = new Float32Array(8);
|
||||
},
|
||||
|
||||
/**
|
||||
* Default configuration of this RenderNode.
|
||||
*
|
||||
* @name Phaser.Renderer.WebGL.RenderNodes.SubmitterTilemapGPULayer#defaultConfig
|
||||
* @type {object}
|
||||
* @since 3.90.0
|
||||
* @readonly
|
||||
* @property {string} name - The name of this RenderNode.
|
||||
* @property {string} vertexSource - The vertex shader source.
|
||||
* @property {string} fragmentSource - The fragment shader source.
|
||||
*/
|
||||
defaultConfig: {
|
||||
name: 'SubmitterTilemapGPULayer',
|
||||
shaderName: 'TilemapGPULayer',
|
||||
vertexSource: ShaderSourceVS,
|
||||
fragmentSource: ShaderSourceFS,
|
||||
shaderAdditions: [
|
||||
MakeSmoothPixelArt(true),
|
||||
MakeSampleNormal(true),
|
||||
MakeDefineLights(true),
|
||||
MakeApplyLighting(true)
|
||||
],
|
||||
vertexBufferLayout: {
|
||||
usage: 'DYNAMIC_DRAW',
|
||||
count: 4,
|
||||
layout: [
|
||||
{
|
||||
name: 'inPosition',
|
||||
size: 2
|
||||
},
|
||||
{
|
||||
name: 'inTexCoord',
|
||||
size: 2
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Fill out the configuration object with default values where needed.
|
||||
*
|
||||
* @method Phaser.Renderer.WebGL.RenderNodes.SubmitterTilemapGPULayer#_completeConfig
|
||||
* @since 3.90.0
|
||||
* @param {object} config - The configuration object to complete.
|
||||
*/
|
||||
_completeLayout: function (config)
|
||||
{
|
||||
// Set up vertex buffer layout.
|
||||
var layoutSource = config.vertexBufferLayout;
|
||||
config.vertexBufferLayout = {};
|
||||
config.vertexBufferLayout.usage = layoutSource.usage;
|
||||
config.vertexBufferLayout.layout = [];
|
||||
var remove = config.vertexBufferLayoutRemove || [];
|
||||
|
||||
for (var i = 0; i < layoutSource.layout.length; i++)
|
||||
{
|
||||
var sourceAttr = layoutSource.layout[i];
|
||||
if (remove.indexOf(sourceAttr.name) !== -1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
config.vertexBufferLayout.layout[i] = {
|
||||
name: sourceAttr.name,
|
||||
size: sourceAttr.size || 1,
|
||||
type: sourceAttr.type || 'FLOAT',
|
||||
normalized: sourceAttr.normalized || false
|
||||
};
|
||||
}
|
||||
|
||||
if (config.vertexBufferLayoutAdd)
|
||||
{
|
||||
var add = config.vertexBufferLayoutAdd || [];
|
||||
for (i = 0; i < add.length; i++)
|
||||
{
|
||||
var addAttr = add[i];
|
||||
config.vertexBufferLayout.layout.push({
|
||||
name: addAttr.name,
|
||||
size: addAttr.size || 1,
|
||||
type: addAttr.type || 'FLOAT',
|
||||
normalized: addAttr.normalized || false
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Set up uniforms for rendering.
|
||||
*
|
||||
* @method Phaser.Renderer.WebGL.RenderNodes.SubmitterTilemapGPULayer#setupUniforms
|
||||
* @since 3.90.0
|
||||
* @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context.
|
||||
* @param {Phaser.Tilemap.TilemapGPULayer} tilemapLayer - The TilemapGPULayer being rendered.
|
||||
*/
|
||||
setupUniforms: function (drawingContext, tilemapLayer)
|
||||
{
|
||||
var camera = drawingContext.camera;
|
||||
var programManager = this.programManager;
|
||||
|
||||
// Standard uniforms.
|
||||
|
||||
programManager.setUniform(
|
||||
'uRoundPixels',
|
||||
camera.roundPixels
|
||||
);
|
||||
|
||||
programManager.setUniform(
|
||||
'uResolution',
|
||||
[ drawingContext.width, drawingContext.height ]
|
||||
);
|
||||
|
||||
drawingContext.renderer.setProjectionMatrix(
|
||||
drawingContext.width,
|
||||
drawingContext.height
|
||||
);
|
||||
programManager.setUniform(
|
||||
'uProjectionMatrix',
|
||||
drawingContext.renderer.projectionMatrix.val
|
||||
);
|
||||
|
||||
// TilemapGPULayer uniforms.
|
||||
|
||||
var tileset = tilemapLayer.tileset;
|
||||
var mainTexture = tileset.glTexture;
|
||||
var layerTexture = tilemapLayer.layerDataTexture;
|
||||
var animTexture = tileset.getAnimationDataTexture(drawingContext.renderer);
|
||||
|
||||
programManager.setUniform('uMainSampler', 0);
|
||||
programManager.setUniform('uLayerSampler', 1);
|
||||
programManager.setUniform('uAnimSampler', 2);
|
||||
|
||||
programManager.setUniform(
|
||||
'uMainResolution',
|
||||
[ mainTexture.width, mainTexture.height ]
|
||||
);
|
||||
|
||||
programManager.setUniform(
|
||||
'uLayerResolution',
|
||||
[ layerTexture.width, layerTexture.height ]
|
||||
);
|
||||
|
||||
programManager.setUniform(
|
||||
'uAnimResolution',
|
||||
[ animTexture.width, animTexture.height ]
|
||||
);
|
||||
|
||||
programManager.setUniform(
|
||||
'uTileColumns',
|
||||
tileset.columns
|
||||
);
|
||||
|
||||
programManager.setUniform(
|
||||
'uTileWidthHeightMarginSpacing',
|
||||
[
|
||||
tileset.tileWidth,
|
||||
tileset.tileHeight,
|
||||
tileset.tileMargin,
|
||||
tileset.tileSpacing
|
||||
]
|
||||
);
|
||||
|
||||
programManager.setUniform(
|
||||
'uAlpha',
|
||||
tilemapLayer.alpha * camera.alpha
|
||||
);
|
||||
|
||||
programManager.setUniform(
|
||||
'uTime',
|
||||
tilemapLayer.timeElapsed
|
||||
);
|
||||
|
||||
// Lighting uniforms.
|
||||
Utils.updateLightingUniforms(
|
||||
tilemapLayer.lighting,
|
||||
this.manager.renderer,
|
||||
drawingContext,
|
||||
programManager,
|
||||
3,
|
||||
this._lightVector,
|
||||
tilemapLayer.selfShadow.enabled,
|
||||
tilemapLayer.selfShadow.diffuseFlatThreshold,
|
||||
tilemapLayer.selfShadow.penumbra
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* Update render options for a TilemapGPULayer object.
|
||||
* This may use a different shader program.
|
||||
* This is called before rendering the object.
|
||||
*
|
||||
* @method Phaser.Renderer.WebGL.RenderNodes.SubmitterTilemapGPULayer#updateRenderOptions
|
||||
* @since 3.90.0
|
||||
* @param {Phaser.Tilemap.TilemapGPULayer} gameObject - The TilemapGPULayer being rendered.
|
||||
*/
|
||||
updateRenderOptions: function (gameObject)
|
||||
{
|
||||
var programManager = this.programManager;
|
||||
var texture = gameObject.tileset.image;
|
||||
|
||||
// Set animation options.
|
||||
var animAddition = programManager.getAdditionsByTag('MAXANIMS')[0];
|
||||
if (animAddition)
|
||||
{
|
||||
programManager.removeAddition(animAddition.name);
|
||||
}
|
||||
if (gameObject.tileset.maxAnimationLength > 0)
|
||||
{
|
||||
programManager.addAddition(
|
||||
MakeAnimLength(gameObject.tileset.maxAnimationLength)
|
||||
);
|
||||
}
|
||||
|
||||
// Set lighting options.
|
||||
var lighting = gameObject.lighting;
|
||||
var lightingAdditions = programManager.getAdditionsByTag('LIGHTING');
|
||||
for (var i = 0; i < lightingAdditions.length; i++)
|
||||
{
|
||||
var addition = lightingAdditions[i];
|
||||
addition.disable = !lighting;
|
||||
}
|
||||
|
||||
if (lighting)
|
||||
{
|
||||
var defineLightsAddition = programManager.getAddition('DefineLights');
|
||||
if (defineLightsAddition)
|
||||
{
|
||||
defineLightsAddition.additions.fragmentDefine =
|
||||
'#define LIGHT_COUNT ' + this.manager.renderer.config.maxLights;
|
||||
}
|
||||
}
|
||||
|
||||
// Set self-shadow options.
|
||||
var selfShadow = gameObject.selfShadow.enabled;
|
||||
if (selfShadow === null)
|
||||
{
|
||||
selfShadow = gameObject.scene.game.config.selfShadow;
|
||||
}
|
||||
if (selfShadow)
|
||||
{
|
||||
programManager.addFeature('SELFSHADOW');
|
||||
}
|
||||
else
|
||||
{
|
||||
programManager.removeFeature('SELFSHADOW');
|
||||
}
|
||||
|
||||
// Set smooth pixel art options.
|
||||
var smoothPixelArt = texture.smoothPixelArt;
|
||||
if (smoothPixelArt === null)
|
||||
{
|
||||
smoothPixelArt = gameObject.scene.game.config.smoothPixelArt;
|
||||
}
|
||||
var smoothPixelArtAddition = programManager.getAddition('SmoothPixelArt');
|
||||
if (smoothPixelArtAddition)
|
||||
{
|
||||
smoothPixelArtAddition.disable = !smoothPixelArt;
|
||||
}
|
||||
|
||||
// Set up border filtering options.
|
||||
var borderFilter = texture.source[0].glTexture.magFilter === this.manager.renderer.gl.LINEAR;
|
||||
if (borderFilter)
|
||||
{
|
||||
programManager.addFeature('BORDERFILTER');
|
||||
}
|
||||
else
|
||||
{
|
||||
programManager.removeFeature('BORDERFILTER');
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Render a TilemapGPULayer object.
|
||||
*
|
||||
* @method Phaser.Renderer.WebGL.RenderNodes.SubmitterTilemapGPULayer#run
|
||||
* @since 3.90.0
|
||||
* @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context.
|
||||
* @param {Phaser.Tilemap.TilemapGPULayer} tilemapLayer - The TilemapGPULayer being rendered.
|
||||
*/
|
||||
run: function (
|
||||
drawingContext,
|
||||
tilemapLayer
|
||||
)
|
||||
{
|
||||
var manager = this.manager;
|
||||
var renderer = manager.renderer;
|
||||
|
||||
manager.startStandAloneRender();
|
||||
|
||||
this.onRunBegin(drawingContext);
|
||||
|
||||
// Transform layer quad.
|
||||
var camera = drawingContext.camera;
|
||||
var spriteMatrix = this._spriteMatrix;
|
||||
var calcMatrix = this._calcMatrix;
|
||||
var quad = this._quad;
|
||||
|
||||
var x = tilemapLayer.x;
|
||||
var y = tilemapLayer.y;
|
||||
var width = tilemapLayer.width;
|
||||
var height = tilemapLayer.height;
|
||||
|
||||
spriteMatrix.applyITRS(x, y, 0, tilemapLayer.scaleX, tilemapLayer.scaleY);
|
||||
spriteMatrix.e -= camera.scrollX * tilemapLayer.scrollFactorX;
|
||||
spriteMatrix.f -= camera.scrollY * tilemapLayer.scrollFactorY;
|
||||
|
||||
// Multiply by the Sprite matrix, store result in calcMatrix
|
||||
camera.matrix.multiply(spriteMatrix, calcMatrix);
|
||||
|
||||
// Compute output quad.
|
||||
calcMatrix.setQuad(
|
||||
x,
|
||||
y,
|
||||
x + width,
|
||||
y + height,
|
||||
false,
|
||||
quad
|
||||
);
|
||||
|
||||
// Populate vertex buffer.
|
||||
var stride = this.vertexBufferLayout.layout.stride;
|
||||
var vertexBuffer = this.vertexBufferLayout.buffer;
|
||||
var vertexF32 = vertexBuffer.viewF32;
|
||||
var offset32 = 0;
|
||||
|
||||
// Bottom Left.
|
||||
vertexF32[offset32++] = quad[2];
|
||||
vertexF32[offset32++] = quad[3];
|
||||
vertexF32[offset32++] = 0;
|
||||
vertexF32[offset32++] = 1;
|
||||
|
||||
// Top Left.
|
||||
vertexF32[offset32++] = quad[0];
|
||||
vertexF32[offset32++] = quad[1];
|
||||
vertexF32[offset32++] = 0;
|
||||
vertexF32[offset32++] = 0;
|
||||
|
||||
// Bottom Right.
|
||||
vertexF32[offset32++] = quad[4];
|
||||
vertexF32[offset32++] = quad[5];
|
||||
vertexF32[offset32++] = 1;
|
||||
vertexF32[offset32++] = 1;
|
||||
|
||||
// Top Right.
|
||||
vertexF32[offset32++] = quad[6];
|
||||
vertexF32[offset32++] = quad[7];
|
||||
vertexF32[offset32++] = 1;
|
||||
vertexF32[offset32++] = 0;
|
||||
|
||||
// console.log('Update vertex buffer', stride, this.vertexBufferLayout, vertexBuffer);
|
||||
|
||||
// Update vertex buffer.
|
||||
// Because we are probably using a generic vertex buffer
|
||||
// which is larger than the current batch, we need to update
|
||||
// the buffer with the correct size.
|
||||
vertexBuffer.update(stride * 4);
|
||||
|
||||
// Assemble textures.
|
||||
var tileset = tilemapLayer.tileset;
|
||||
var mainGlTexture = tileset.glTexture;
|
||||
var animated = tileset.getAnimationDataIndexMap(renderer).size > 0;
|
||||
|
||||
var textures = [
|
||||
mainGlTexture,
|
||||
tilemapLayer.layerDataTexture
|
||||
];
|
||||
|
||||
if (animated)
|
||||
{
|
||||
textures[2] = tileset.getAnimationDataTexture(renderer);
|
||||
}
|
||||
|
||||
if (tilemapLayer.lighting)
|
||||
{
|
||||
var texture = tileset.image;
|
||||
var normalMap = texture.dataSource[0];
|
||||
if (!normalMap)
|
||||
{
|
||||
normalMap = this.manager.renderer.normalTexture;
|
||||
}
|
||||
else
|
||||
{
|
||||
normalMap = normalMap.glTexture;
|
||||
}
|
||||
textures[3] = normalMap;
|
||||
}
|
||||
|
||||
this.updateRenderOptions(tilemapLayer);
|
||||
|
||||
var programManager = this.programManager;
|
||||
var programSuite = programManager.getCurrentProgramSuite();
|
||||
var program = programSuite.program;
|
||||
var vao = programSuite.vao;
|
||||
|
||||
this.setupUniforms(drawingContext, tilemapLayer);
|
||||
programManager.applyUniforms(program);
|
||||
|
||||
// Render layer.
|
||||
renderer.drawElements(
|
||||
drawingContext,
|
||||
textures,
|
||||
program,
|
||||
vao,
|
||||
4,
|
||||
0
|
||||
);
|
||||
|
||||
this.onRunEnd(drawingContext);
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = SubmitterTilemapGPULayer;
|
16
src/renderer/webgl/shaders/ApplyBlockyTexCoord-glsl.js
Normal file
16
src/renderer/webgl/shaders/ApplyBlockyTexCoord-glsl.js
Normal file
|
@ -0,0 +1,16 @@
|
|||
module.exports = [
|
||||
'#if TEXTURE_COUNT == 1',
|
||||
'texCoord = getBlockyTexCoord(texCoord, uMainResolution);',
|
||||
'#else',
|
||||
'vec2 texRes;',
|
||||
'for (int i = 0; i < TEXTURE_COUNT; i++)',
|
||||
'{',
|
||||
' if (outTexDatum == float(i))',
|
||||
' {',
|
||||
' texRes = uMainResolution[i];',
|
||||
' break;',
|
||||
' }',
|
||||
'}',
|
||||
'texCoord = getBlockyTexCoord(texCoord, texRes);',
|
||||
'#endif',
|
||||
].join('\n');
|
|
@ -1,58 +1,7 @@
|
|||
module.exports = [
|
||||
'struct Light',
|
||||
'vec4 applyLighting (vec4 fragColor, vec3 normal)',
|
||||
'{',
|
||||
' vec3 position;',
|
||||
' vec3 color;',
|
||||
' float intensity;',
|
||||
' float radius;',
|
||||
'};',
|
||||
'const int kMaxLights = LIGHT_COUNT;',
|
||||
'uniform vec4 uCamera; /* x, y, rotation, zoom */',
|
||||
'uniform sampler2D uNormSampler;',
|
||||
'uniform vec3 uAmbientLightColor;',
|
||||
'uniform Light uLights[kMaxLights];',
|
||||
'uniform int uLightCount;',
|
||||
'#ifdef FEATURE_SELFSHADOW',
|
||||
'uniform float uDiffuseFlatThreshold;',
|
||||
'uniform float uPenumbra;',
|
||||
'#endif',
|
||||
'vec4 applyLighting (vec4 fragColor)',
|
||||
'{',
|
||||
' vec3 finalColor = vec3(0.0);',
|
||||
' #ifdef FEATURE_FLAT_LIGHTING',
|
||||
' vec3 normal = vec3(0.0, 0.0, 1.0);',
|
||||
' #else',
|
||||
' vec2 texCoord = outTexCoord;',
|
||||
' vec3 normalMap = texture2D(uNormSampler, texCoord).rgb;',
|
||||
' vec3 normal = normalize(outInverseRotationMatrix * vec3(normalMap * 2.0 - 1.0));',
|
||||
' #endif',
|
||||
' vec2 res = vec2(min(uResolution.x, uResolution.y)) * uCamera.w;',
|
||||
' #ifdef FEATURE_SELFSHADOW',
|
||||
' vec3 unpremultipliedColor = fragColor.rgb / fragColor.a;',
|
||||
' float occlusionThreshold = 1.0 - ((unpremultipliedColor.r + unpremultipliedColor.g + unpremultipliedColor.b) / uDiffuseFlatThreshold);',
|
||||
' #endif',
|
||||
' for (int index = 0; index < kMaxLights; ++index)',
|
||||
' {',
|
||||
' if (index < uLightCount)',
|
||||
' {',
|
||||
' Light light = uLights[index];',
|
||||
' vec3 lightDir = vec3((light.position.xy / res) - (gl_FragCoord.xy / res), light.position.z / res.x);',
|
||||
' vec3 lightNormal = normalize(lightDir);',
|
||||
' float distToSurf = length(lightDir) * uCamera.w;',
|
||||
' float diffuseFactor = max(dot(normal, lightNormal), 0.0);',
|
||||
' float radius = (light.radius / res.x * uCamera.w) * uCamera.w;',
|
||||
' float attenuation = clamp(1.0 - distToSurf * distToSurf / (radius * radius), 0.0, 1.0);',
|
||||
' #ifdef FEATURE_SELFSHADOW',
|
||||
' float occluded = smoothstep(0.0, 1.0, (diffuseFactor - occlusionThreshold) / uPenumbra);',
|
||||
' vec3 diffuse = light.color * diffuseFactor * occluded;',
|
||||
' #else',
|
||||
' vec3 diffuse = light.color * diffuseFactor;',
|
||||
' #endif',
|
||||
' finalColor += (attenuation * diffuse) * light.intensity;',
|
||||
' }',
|
||||
' }',
|
||||
' vec4 colorOutput = vec4(uAmbientLightColor + finalColor, 1.0);',
|
||||
' fragColor *= vec4(colorOutput.rgb * colorOutput.a, colorOutput.a);',
|
||||
' return fragColor;',
|
||||
' vec4 lighting = getLighting(fragColor, normal);',
|
||||
' return fragColor * vec4(lighting.rgb * lighting.a, lighting.a);',
|
||||
'}',
|
||||
].join('\n');
|
||||
|
|
13
src/renderer/webgl/shaders/DefineBlockyTexCoord-glsl.js
Normal file
13
src/renderer/webgl/shaders/DefineBlockyTexCoord-glsl.js
Normal file
|
@ -0,0 +1,13 @@
|
|||
module.exports = [
|
||||
'vec2 v2len (vec2 a, vec2 b)',
|
||||
'{',
|
||||
' return sqrt(a*a+b*b);',
|
||||
'}',
|
||||
'vec2 getBlockyTexCoord (vec2 texCoord, vec2 texRes) {',
|
||||
' texCoord *= texRes;',
|
||||
' vec2 seam = floor(texCoord + 0.5);',
|
||||
' texCoord = (texCoord - seam) / v2len(dFdx(texCoord), dFdy(texCoord)) + seam;',
|
||||
' texCoord = clamp(texCoord, seam-.5, seam+.5);',
|
||||
' return texCoord / texRes;',
|
||||
'}',
|
||||
].join('\n');
|
50
src/renderer/webgl/shaders/DefineLights-glsl.js
Normal file
50
src/renderer/webgl/shaders/DefineLights-glsl.js
Normal file
|
@ -0,0 +1,50 @@
|
|||
module.exports = [
|
||||
'struct Light',
|
||||
'{',
|
||||
' vec3 position;',
|
||||
' vec3 color;',
|
||||
' float intensity;',
|
||||
' float radius;',
|
||||
'};',
|
||||
'const int kMaxLights = LIGHT_COUNT;',
|
||||
'uniform vec4 uCamera; /* x, y, rotation, zoom */',
|
||||
'uniform sampler2D uNormSampler;',
|
||||
'uniform vec3 uAmbientLightColor;',
|
||||
'uniform Light uLights[kMaxLights];',
|
||||
'uniform int uLightCount;',
|
||||
'#ifdef FEATURE_SELFSHADOW',
|
||||
'uniform float uDiffuseFlatThreshold;',
|
||||
'uniform float uPenumbra;',
|
||||
'#endif',
|
||||
'vec4 getLighting (vec4 fragColor, vec3 normal)',
|
||||
'{',
|
||||
' vec3 finalColor = vec3(0.0);',
|
||||
' vec2 res = vec2(min(uResolution.x, uResolution.y)) * uCamera.w;',
|
||||
' #ifdef FEATURE_SELFSHADOW',
|
||||
' vec3 unpremultipliedColor = fragColor.rgb / fragColor.a;',
|
||||
' float occlusionThreshold = 1.0 - ((unpremultipliedColor.r + unpremultipliedColor.g + unpremultipliedColor.b) / uDiffuseFlatThreshold);',
|
||||
' #endif',
|
||||
' for (int index = 0; index < kMaxLights; ++index)',
|
||||
' {',
|
||||
' if (index < uLightCount)',
|
||||
' {',
|
||||
' Light light = uLights[index];',
|
||||
' vec3 lightDir = vec3((light.position.xy / res) - (gl_FragCoord.xy / res), light.position.z / res.x);',
|
||||
' vec3 lightNormal = normalize(lightDir);',
|
||||
' float distToSurf = length(lightDir) * uCamera.w;',
|
||||
' float diffuseFactor = max(dot(normal, lightNormal), 0.0);',
|
||||
' float radius = (light.radius / res.x * uCamera.w) * uCamera.w;',
|
||||
' float attenuation = clamp(1.0 - distToSurf * distToSurf / (radius * radius), 0.0, 1.0);',
|
||||
' #ifdef FEATURE_SELFSHADOW',
|
||||
' float occluded = smoothstep(0.0, 1.0, (diffuseFactor - occlusionThreshold) / uPenumbra);',
|
||||
' vec3 diffuse = light.color * diffuseFactor * occluded;',
|
||||
' #else',
|
||||
' vec3 diffuse = light.color * diffuseFactor;',
|
||||
' #endif',
|
||||
' finalColor += (attenuation * diffuse) * light.intensity;',
|
||||
' }',
|
||||
' }',
|
||||
' vec4 colorOutput = vec4(uAmbientLightColor + finalColor, 1.0);',
|
||||
' return colorOutput;',
|
||||
'}'
|
||||
].join('\n');
|
10
src/renderer/webgl/shaders/DefineTexCoordFrameClamp-glsl.js
Normal file
10
src/renderer/webgl/shaders/DefineTexCoordFrameClamp-glsl.js
Normal file
|
@ -0,0 +1,10 @@
|
|||
module.exports = [
|
||||
'vec2 clampTexCoordWithinFrame (vec2 texCoord)',
|
||||
'{',
|
||||
' vec2 texRes = getTexRes();',
|
||||
' vec4 frameTexel = outFrame * texRes.xyxy;',
|
||||
' vec2 frameMin = frameTexel.xy + vec2(0.5, 0.5);',
|
||||
' vec2 frameMax = frameTexel.xy + frameTexel.zw - vec2(0.5, 0.5);',
|
||||
' return clamp(texCoord, frameMin / texRes, frameMax / texRes);',
|
||||
'}',
|
||||
].join('\n');
|
|
@ -1,5 +1,6 @@
|
|||
module.exports = [
|
||||
'#pragma phaserTemplate(shaderName)',
|
||||
'#pragma phaserTemplate(extensions)',
|
||||
'#pragma phaserTemplate(features)',
|
||||
'#ifdef GL_FRAGMENT_PRECISION_HIGH',
|
||||
'precision highp float;',
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
module.exports = [
|
||||
'#pragma phaserTemplate(shaderName)',
|
||||
'#pragma phaserTemplate(extensions)',
|
||||
'#pragma phaserTemplate(features)',
|
||||
'precision mediump float;',
|
||||
'#pragma phaserTemplate(vertexDefine)',
|
||||
|
|
7
src/renderer/webgl/shaders/GetNormalFromMap-glsl.js
Normal file
7
src/renderer/webgl/shaders/GetNormalFromMap-glsl.js
Normal file
|
@ -0,0 +1,7 @@
|
|||
module.exports = [
|
||||
'vec3 getNormalFromMap (vec2 texCoord)',
|
||||
'{',
|
||||
' vec3 normalMap = texture2D(uNormSampler, texCoord).rgb;',
|
||||
' return normalize(outInverseRotationMatrix * vec3(normalMap * 2.0 - 1.0));',
|
||||
'}',
|
||||
].join('\n');
|
22
src/renderer/webgl/shaders/GetTexRes-glsl.js
Normal file
22
src/renderer/webgl/shaders/GetTexRes-glsl.js
Normal file
|
@ -0,0 +1,22 @@
|
|||
module.exports = [
|
||||
'uniform vec2 uMainResolution[TEXTURE_COUNT];',
|
||||
'vec2 getTexRes ()',
|
||||
'{',
|
||||
' #if TEXTURE_COUNT == 1',
|
||||
' float texId = 0.0;',
|
||||
' #else',
|
||||
' float texId = outTexDatum;',
|
||||
' #endif',
|
||||
' #pragma phaserTemplate(texIdProcess)',
|
||||
' vec2 texRes = vec2(0.0);',
|
||||
' for (int i = 0; i < TEXTURE_COUNT; i++)',
|
||||
' {',
|
||||
' if (texId == float(i))',
|
||||
' {',
|
||||
' texRes = uMainResolution[i];',
|
||||
' break;',
|
||||
' }',
|
||||
' }',
|
||||
' return texRes;',
|
||||
'}',
|
||||
].join('\n');
|
22
src/renderer/webgl/shaders/GetTexture-glsl.js
Normal file
22
src/renderer/webgl/shaders/GetTexture-glsl.js
Normal file
|
@ -0,0 +1,22 @@
|
|||
module.exports = [
|
||||
'uniform sampler2D uMainSampler[TEXTURE_COUNT];',
|
||||
'vec4 getTexture (vec2 texCoord)',
|
||||
'{',
|
||||
' #if TEXTURE_COUNT == 1',
|
||||
' float texId = 0.0;',
|
||||
' #else',
|
||||
' float texId = outTexDatum;',
|
||||
' #endif',
|
||||
' #pragma phaserTemplate(texIdProcess)',
|
||||
' vec4 texture = vec4(0.0);',
|
||||
' for (int i = 0; i < TEXTURE_COUNT; i++)',
|
||||
' {',
|
||||
' if (texId == float(i))',
|
||||
' {',
|
||||
' texture = texture2D(uMainSampler[i], texCoord);',
|
||||
' break;',
|
||||
' }',
|
||||
' }',
|
||||
' return texture;',
|
||||
'}'
|
||||
].join('\n');
|
|
@ -1,13 +0,0 @@
|
|||
module.exports = [
|
||||
'uniform sampler2D uMainSampler[TEXTURE_COUNT];',
|
||||
'vec4 getTexture ()',
|
||||
'{',
|
||||
' float texId = outTexDatum;',
|
||||
' #pragma phaserTemplate(texIdProcess)',
|
||||
' vec2 texCoord = outTexCoord;',
|
||||
' #pragma phaserTemplate(texCoordProcess)',
|
||||
' vec4 texture = vec4(0.0);',
|
||||
' #pragma phaserTemplate(texSamplerProcess)',
|
||||
' return texture;',
|
||||
'}',
|
||||
].join('\n');
|
|
@ -1,9 +0,0 @@
|
|||
module.exports = [
|
||||
'uniform sampler2D uMainSampler;',
|
||||
'vec4 getTexture ()',
|
||||
'{',
|
||||
' vec2 texCoord = outTexCoord;',
|
||||
' #pragma phaserTemplate(texCoordProcess)',
|
||||
' return texture2D(uMainSampler, texCoord);',
|
||||
'}',
|
||||
].join('\n');
|
|
@ -1,5 +1,6 @@
|
|||
module.exports = [
|
||||
'#pragma phaserTemplate(shaderName)',
|
||||
'#pragma phaserTemplate(extensions)',
|
||||
'#pragma phaserTemplate(features)',
|
||||
'#ifdef GL_FRAGMENT_PRECISION_HIGH',
|
||||
'precision highp float;',
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
module.exports = [
|
||||
'#pragma phaserTemplate(shaderName)',
|
||||
'#pragma phaserTemplate(extensions)',
|
||||
'#pragma phaserTemplate(features)',
|
||||
'#ifdef GL_FRAGMENT_PRECISION_HIGH',
|
||||
'precision highp float;',
|
||||
|
|
10
src/renderer/webgl/shaders/OutInverseRotation-glsl.js
Normal file
10
src/renderer/webgl/shaders/OutInverseRotation-glsl.js
Normal file
|
@ -0,0 +1,10 @@
|
|||
module.exports = [
|
||||
'float inverseRotation = -rotation - uCamera.z;',
|
||||
'float irSine = sin(inverseRotation);',
|
||||
'float irCosine = cos(inverseRotation);',
|
||||
'outInverseRotationMatrix = mat3(',
|
||||
' irCosine, irSine, 0.0,',
|
||||
' -irSine, irCosine, 0.0,',
|
||||
' 0.0, 0.0, 1.0',
|
||||
');',
|
||||
].join('\n');
|
|
@ -1,5 +1,6 @@
|
|||
module.exports = [
|
||||
'#pragma phaserTemplate(shaderName)',
|
||||
'#pragma phaserTemplate(extensions)',
|
||||
'#pragma phaserTemplate(features)',
|
||||
'precision mediump float;',
|
||||
'#pragma phaserTemplate(fragmentDefine)',
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
module.exports = [
|
||||
'#pragma phaserTemplate(shaderName)',
|
||||
'#pragma phaserTemplate(extensions)',
|
||||
'#pragma phaserTemplate(features)',
|
||||
'precision mediump float;',
|
||||
'#pragma phaserTemplate(vertexDefine)',
|
||||
|
|
233
src/renderer/webgl/shaders/TilemapGPULayer-frag.js
Normal file
233
src/renderer/webgl/shaders/TilemapGPULayer-frag.js
Normal file
|
@ -0,0 +1,233 @@
|
|||
module.exports = [
|
||||
'#version 100',
|
||||
'#pragma phaserTemplate(shaderName)',
|
||||
'#pragma phaserTemplate(extensions)',
|
||||
'#pragma phaserTemplate(features)',
|
||||
'#ifdef GL_FRAGMENT_PRECISION_HIGH',
|
||||
'precision highp float;',
|
||||
'#else',
|
||||
'precision mediump float;',
|
||||
'#endif',
|
||||
'/* Redefine MAX_ANIM_FRAMES to support animations with different frame numbers. */',
|
||||
'#define MAX_ANIM_FRAMES 0',
|
||||
'#pragma phaserTemplate(fragmentDefine)',
|
||||
'uniform vec2 uResolution;',
|
||||
'uniform int roundPixels;',
|
||||
'uniform sampler2D uMainSampler;',
|
||||
'uniform sampler2D uLayerSampler;',
|
||||
'uniform vec2 uMainResolution;',
|
||||
'uniform vec2 uLayerResolution;',
|
||||
'uniform float uTileColumns;',
|
||||
'uniform vec4 uTileWidthHeightMarginSpacing;',
|
||||
'uniform float uAlpha;',
|
||||
'uniform float uTime;',
|
||||
'#if MAX_ANIM_FRAMES > 0',
|
||||
'uniform sampler2D uAnimSampler;',
|
||||
'uniform vec2 uAnimResolution;',
|
||||
'#endif',
|
||||
'varying vec2 outTexCoord;',
|
||||
'varying vec2 outTileStride;',
|
||||
'#pragma phaserTemplate(outVariables)',
|
||||
'vec2 getTexRes ()',
|
||||
'{',
|
||||
' return uMainResolution;',
|
||||
'}',
|
||||
'float floatTexel (vec4 texel)',
|
||||
'{',
|
||||
' return texel.r * 255.0 + (texel.g * 255.0 * 256.0) + (texel.b * 255.0 * 256.0 * 256.0) + (texel.a * 255.0 * 256.0 * 256.0 * 256.0);',
|
||||
'}',
|
||||
'struct Tile',
|
||||
'{',
|
||||
' float index;',
|
||||
' vec2 uv; // In texels.',
|
||||
' #if MAX_ANIM_FRAMES > 0',
|
||||
' bool animated;',
|
||||
' #endif',
|
||||
' bool empty;',
|
||||
'};',
|
||||
'Tile getLayerData (vec2 coord)',
|
||||
'{',
|
||||
' vec2 texelCoord = coord * uLayerResolution;',
|
||||
' vec2 tile = floor(texelCoord);',
|
||||
' vec2 uv = fract(texelCoord);',
|
||||
' vec4 texel = texture2D(uLayerSampler, (tile + 0.5) / uLayerResolution) * 255.0;',
|
||||
' float flags = texel.a;',
|
||||
' /* Check for empty tile flag in bit 28. */',
|
||||
' if (flags == 16.0)',
|
||||
' {',
|
||||
' return Tile(',
|
||||
' 0.0,',
|
||||
' vec2(0.0),',
|
||||
' #if MAX_ANIM_FRAMES > 0',
|
||||
' false,',
|
||||
' #endif',
|
||||
' true',
|
||||
' );',
|
||||
' }',
|
||||
' /* Bit 31 is flipX. */',
|
||||
' bool flipX = flags > 127.0;',
|
||||
' /* Bit 30 is flipY. */',
|
||||
' bool flipY = mod(flags, 128.0) > 63.0;',
|
||||
' #if MAX_ANIM_FRAMES > 0',
|
||||
' /* Bit 29 is animation. */',
|
||||
' bool animated = mod(flags, 64.0) > 31.0;',
|
||||
' #endif',
|
||||
' if (flipX)',
|
||||
' {',
|
||||
' uv.x = 1.0 - uv.x;',
|
||||
' }',
|
||||
' if (flipY)',
|
||||
' {',
|
||||
' uv.y = 1.0 - uv.y;',
|
||||
' }',
|
||||
' float index = texel.r + (texel.g * 256.0) + (texel.b * 256.0 * 256.0);',
|
||||
' return Tile(',
|
||||
' index,',
|
||||
' uv * uTileWidthHeightMarginSpacing.xy,',
|
||||
' #if MAX_ANIM_FRAMES > 0',
|
||||
' animated,',
|
||||
' #endif',
|
||||
' false',
|
||||
' );',
|
||||
'}',
|
||||
'vec2 getFrameCorner (float index)',
|
||||
'{',
|
||||
' float x = mod(index, uTileColumns);',
|
||||
' float y = floor(index / uTileColumns);',
|
||||
' vec2 xy = vec2(x, y);',
|
||||
' return xy * outTileStride + uTileWidthHeightMarginSpacing.zz;',
|
||||
'}',
|
||||
'#if MAX_ANIM_FRAMES > 0',
|
||||
'float animationIndex (float index)',
|
||||
'{',
|
||||
' float animTextureWidth = uAnimResolution.x;',
|
||||
' vec2 index2D = vec2(mod(index, animTextureWidth), floor(index / animTextureWidth));',
|
||||
' vec4 animDurationTexel = texture2D(uAnimSampler, (index2D + 0.5) / uAnimResolution);',
|
||||
' index2D = vec2(mod(index + 1.0, animTextureWidth), floor((index + 1.0) / animTextureWidth));',
|
||||
' vec4 animIndexTexel = texture2D(uAnimSampler, (index2D + 0.5) / uAnimResolution);',
|
||||
' float animDuration = floatTexel(animDurationTexel);',
|
||||
' float animIndex = floatTexel(animIndexTexel);',
|
||||
' float animTime = mod(uTime, animDuration);',
|
||||
' float animTimeAccum = 0.0;',
|
||||
' for (int i = 0; i < MAX_ANIM_FRAMES; i++)',
|
||||
' {',
|
||||
' index2D = vec2(mod(animIndex, animTextureWidth), floor(animIndex / animTextureWidth));',
|
||||
' animDurationTexel = texture2D(uAnimSampler, (index2D + 0.5) / uAnimResolution);',
|
||||
' float frameDuration = floatTexel(animDurationTexel);',
|
||||
' animTimeAccum += frameDuration;',
|
||||
' if (animTime <= animTimeAccum)',
|
||||
' {',
|
||||
' break;',
|
||||
' }',
|
||||
' animIndex += 2.0;',
|
||||
' }',
|
||||
' animIndex += 1.0;',
|
||||
' index2D = vec2(mod(animIndex, animTextureWidth), floor(animIndex / animTextureWidth));',
|
||||
' animIndexTexel = texture2D(uAnimSampler, (index2D + 0.5) / uAnimResolution);',
|
||||
' float animFrameIndex = floatTexel(animIndexTexel);',
|
||||
' return animFrameIndex;',
|
||||
'}',
|
||||
'#endif',
|
||||
'vec2 getTileTexelCoord (Tile tile)',
|
||||
'{',
|
||||
' if (tile.empty)',
|
||||
' {',
|
||||
' return vec2(0.0);',
|
||||
' }',
|
||||
' float index = tile.index;',
|
||||
' #if MAX_ANIM_FRAMES > 0',
|
||||
' if (tile.animated)',
|
||||
' {',
|
||||
' index = animationIndex(index);',
|
||||
' }',
|
||||
' #endif',
|
||||
' vec2 frameCorner = getFrameCorner(index);',
|
||||
' return frameCorner + tile.uv;',
|
||||
'}',
|
||||
'#pragma phaserTemplate(fragmentHeader)',
|
||||
'struct Samples {',
|
||||
' vec4 color;',
|
||||
' #pragma phaserTemplate(defineSamples)',
|
||||
'};',
|
||||
'Samples getColorSamples (vec2 texCoord)',
|
||||
'{',
|
||||
' Samples samples;',
|
||||
' samples.color = texture2D(uMainSampler, texCoord);',
|
||||
' #pragma phaserTemplate(getSamples)',
|
||||
' return samples;',
|
||||
'}',
|
||||
'Samples mixSamples (Samples samples1, Samples samples2, float alpha)',
|
||||
'{',
|
||||
' Samples samples;',
|
||||
' samples.color = mix(samples1.color, samples2.color, alpha);',
|
||||
' #pragma phaserTemplate(mixSamples)',
|
||||
' return samples;',
|
||||
'}',
|
||||
'Samples getFinalSamples (Tile tile, vec2 layerTexCoord)',
|
||||
'{',
|
||||
' vec2 texelCoord = getTileTexelCoord(tile);',
|
||||
' vec2 texCoord = texelCoord / uMainResolution;',
|
||||
' #pragma phaserTemplate(texCoord)',
|
||||
' #ifndef FEATURE_BORDERFILTER',
|
||||
' return getColorSamples(texCoord);',
|
||||
' #else',
|
||||
' #pragma phaserTemplate(finalSamples)',
|
||||
' vec2 wh = uTileWidthHeightMarginSpacing.xy;',
|
||||
' vec2 frameCorner = getFrameCorner(tile.index);',
|
||||
' vec2 frameCornerOpposite = frameCorner + wh;',
|
||||
' vec2 texCoordClamped = clamp(texCoord, (frameCorner + 0.5) / uMainResolution, (frameCornerOpposite - 0.5) / uMainResolution);',
|
||||
' vec2 dTexelCoord = (texCoord - texCoordClamped) * uMainResolution;',
|
||||
' vec2 offsets = sign(dTexelCoord);',
|
||||
' Samples samples0 = getColorSamples(texCoordClamped);',
|
||||
' if (offsets.x == 0.0)',
|
||||
' {',
|
||||
' if (offsets.y == 0.0)',
|
||||
' {',
|
||||
' return samples0;',
|
||||
' }',
|
||||
' Tile tileY = getLayerData(layerTexCoord + (offsets - dTexelCoord) / wh / uLayerResolution);',
|
||||
' vec2 texelCoordY = getTileTexelCoord(tileY);',
|
||||
' vec2 texCoordY = texelCoordY / uMainResolution;',
|
||||
' Samples samplesY = getColorSamples(texCoordY);',
|
||||
' return mixSamples(samples0, samplesY, abs(dTexelCoord.y));',
|
||||
' }',
|
||||
' else',
|
||||
' {',
|
||||
' if (offsets.y == 0.0)',
|
||||
' {',
|
||||
' Tile tileX = getLayerData(layerTexCoord + (offsets - dTexelCoord) / wh / uLayerResolution);',
|
||||
' vec2 texelCoordX = getTileTexelCoord(tileX);',
|
||||
' vec2 texCoordX = texelCoordX / uMainResolution;',
|
||||
' Samples samplesX = getColorSamples(texCoordX);',
|
||||
' return mixSamples(samples0, samplesX, abs(dTexelCoord.x));',
|
||||
' }',
|
||||
' Tile tileX = getLayerData(layerTexCoord + (offsets * vec2(1.0, 0.0) - dTexelCoord) / wh / uLayerResolution);',
|
||||
' vec2 texelCoordX = getTileTexelCoord(tileX);',
|
||||
' vec2 texCoordX = texelCoordX / uMainResolution;',
|
||||
' Samples samplesX = getColorSamples(texCoordX);',
|
||||
' Tile tileY = getLayerData(layerTexCoord + (offsets * vec2(0.0, 1.0) - dTexelCoord) / wh / uLayerResolution);',
|
||||
' vec2 texelCoordY = getTileTexelCoord(tileY);',
|
||||
' vec2 texCoordY = texelCoordY / uMainResolution;',
|
||||
' Samples samplesY = getColorSamples(texCoordY);',
|
||||
' Tile tileXY = getLayerData(layerTexCoord + (offsets - dTexelCoord) / wh / uLayerResolution);',
|
||||
' vec2 texelCoordXY = getTileTexelCoord(tileXY);',
|
||||
' vec2 texCoordXY = texelCoordXY / uMainResolution;',
|
||||
' Samples samplesXY = getColorSamples(texCoordXY);',
|
||||
' Samples samples1 = mixSamples(samples0, samplesX, abs(dTexelCoord.x));',
|
||||
' Samples samples2 = mixSamples(samplesY, samplesXY, abs(dTexelCoord.x));',
|
||||
' return mixSamples(samples1, samples2, abs(dTexelCoord.y));',
|
||||
' }',
|
||||
' #endif',
|
||||
'}',
|
||||
'void main ()',
|
||||
'{',
|
||||
' vec2 layerTexCoord = outTexCoord;',
|
||||
' Tile tile = getLayerData(layerTexCoord);',
|
||||
' Samples samples = getFinalSamples(tile, layerTexCoord);',
|
||||
' vec4 fragColor = samples.color;',
|
||||
' #pragma phaserTemplate(declareSamples)',
|
||||
' #pragma phaserTemplate(fragmentProcess)',
|
||||
' fragColor *= uAlpha;',
|
||||
' gl_FragColor = fragColor;',
|
||||
'}',
|
||||
].join('\n');
|
32
src/renderer/webgl/shaders/TilemapGPULayer-vert.js
Normal file
32
src/renderer/webgl/shaders/TilemapGPULayer-vert.js
Normal file
|
@ -0,0 +1,32 @@
|
|||
module.exports = [
|
||||
'#pragma phaserTemplate(shaderName)',
|
||||
'#pragma phaserTemplate(extensions)',
|
||||
'#pragma phaserTemplate(features)',
|
||||
'#ifdef GL_FRAGMENT_PRECISION_HIGH',
|
||||
'precision highp float;',
|
||||
'#else',
|
||||
'precision mediump float;',
|
||||
'#endif',
|
||||
'#pragma phaserTemplate(vertexDefine)',
|
||||
'uniform mat4 uProjectionMatrix;',
|
||||
'uniform int uRoundPixels;',
|
||||
'uniform vec2 uResolution;',
|
||||
'uniform vec4 uTileWidthHeightMarginSpacing;',
|
||||
'attribute vec2 inPosition;',
|
||||
'attribute vec2 inTexCoord;',
|
||||
'varying vec2 outTexCoord;',
|
||||
'varying vec2 outTileStride;',
|
||||
'#pragma phaserTemplate(outVariables)',
|
||||
'#pragma phaserTemplate(vertexHeader)',
|
||||
'void main ()',
|
||||
'{',
|
||||
' gl_Position = uProjectionMatrix * vec4(inPosition, 1.0, 1.0);',
|
||||
' if (uRoundPixels == 1)',
|
||||
' {',
|
||||
' gl_Position.xy = floor(((gl_Position.xy + 1.0) * 0.5 * uResolution) + 0.5) / uResolution * 2.0 - 1.0;',
|
||||
' }',
|
||||
' outTexCoord = inTexCoord;',
|
||||
' outTileStride = uTileWidthHeightMarginSpacing.xy + uTileWidthHeightMarginSpacing.zz;',
|
||||
' #pragma phaserTemplate(vertexProcess)',
|
||||
'}',
|
||||
].join('\n');
|
19
src/renderer/webgl/shaders/configs/MakeAnimLength.js
Normal file
19
src/renderer/webgl/shaders/configs/MakeAnimLength.js
Normal file
|
@ -0,0 +1,19 @@
|
|||
/**
|
||||
* @author Benjamin D. Richards <benjamindrichards@gmail.com>
|
||||
* @copyright 2013-2024 Phaser Studio Inc.
|
||||
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
||||
*/
|
||||
|
||||
var MakeAnimLength = function (maxAnims, disable)
|
||||
{
|
||||
return {
|
||||
name: maxAnims + 'Anims',
|
||||
additions: {
|
||||
fragmentDefine: '#undef MAX_ANIM_FRAMES\n#define MAX_ANIM_FRAMES ' + maxAnims
|
||||
},
|
||||
tags: [ 'MAXANIMS' ],
|
||||
disable: !!disable
|
||||
};
|
||||
};
|
||||
|
||||
module.exports = MakeAnimLength;
|
30
src/renderer/webgl/shaders/configs/MakeApplyFlatLighting.js
Normal file
30
src/renderer/webgl/shaders/configs/MakeApplyFlatLighting.js
Normal file
|
@ -0,0 +1,30 @@
|
|||
/**
|
||||
* @author Benjamin D. Richards <benjamindrichards@gmail.com>
|
||||
* @copyright 2013-2024 Phaser Studio Inc.
|
||||
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
||||
*/
|
||||
|
||||
var ApplyLighting = require('../ApplyLighting-glsl');
|
||||
|
||||
/**
|
||||
* Return a ShaderAdditionConfig for applying lighting to a flat piece of geometry.
|
||||
*
|
||||
* @function Phaser.Renderer.WebGL.Shaders.MakeApplyFlatLighting
|
||||
* @since 3.90.0
|
||||
* @param {boolean} [disable=false] - Whether to disable the shader addition on creation.
|
||||
* @returns {Phaser.Types.Renderer.WebGL.ShaderAdditionConfig} The shader addition configuration.
|
||||
*/
|
||||
var MakeApplyFlatLighting = function (disable)
|
||||
{
|
||||
return {
|
||||
name: 'ApplyFlatLighting',
|
||||
additions: {
|
||||
fragmentHeader: ApplyLighting,
|
||||
fragmentProcess: 'fragColor = applyLighting(fragColor, vec3(0.0, 0.0, 1.0));'
|
||||
},
|
||||
tags: ['LIGHTING'],
|
||||
disable: !!disable
|
||||
};
|
||||
};
|
||||
|
||||
module.exports = MakeApplyFlatLighting;
|
|
@ -6,20 +6,6 @@
|
|||
|
||||
var ApplyLighting = require('../ApplyLighting-glsl');
|
||||
|
||||
var inverseRotation = [
|
||||
'',
|
||||
'#ifndef FEATURE_FLAT_LIGHTING',
|
||||
'float inverseRotation = -rotation - uCamera.z;',
|
||||
'float irSine = sin(inverseRotation);',
|
||||
'float irCosine = cos(inverseRotation);',
|
||||
'outInverseRotationMatrix = mat3(',
|
||||
' irCosine, irSine, 0.0,',
|
||||
' -irSine, irCosine, 0.0,',
|
||||
' 0.0, 0.0, 1.0',
|
||||
');',
|
||||
'#endif'
|
||||
].join('\n ');
|
||||
|
||||
/**
|
||||
* Return a ShaderAdditionConfig for applying lighting to a texture.
|
||||
*
|
||||
|
@ -33,14 +19,10 @@ var inverseRotation = [
|
|||
var MakeApplyLighting = function (disable)
|
||||
{
|
||||
return {
|
||||
name: 'LIGHTING',
|
||||
name: 'ApplyLighting',
|
||||
additions: {
|
||||
vertexHeader: 'uniform vec4 uCamera;',
|
||||
vertexProcess: inverseRotation,
|
||||
outVariables: 'varying mat3 outInverseRotationMatrix;',
|
||||
fragmentDefine: '#define LIGHT_COUNT 1',
|
||||
fragmentHeader: ApplyLighting,
|
||||
fragmentProcess: 'fragColor = applyLighting(fragColor);'
|
||||
fragmentProcess: 'fragColor = applyLighting(fragColor, normal);'
|
||||
},
|
||||
tags: ['LIGHTING'],
|
||||
disable: !!disable
|
||||
|
|
|
@ -17,7 +17,7 @@ var ApplyTint = require('../ApplyTint-glsl');
|
|||
var MakeApplyTint = function (disable)
|
||||
{
|
||||
return {
|
||||
name: 'TINT',
|
||||
name: 'Tint',
|
||||
additions: {
|
||||
fragmentHeader: ApplyTint,
|
||||
fragmentProcess: 'fragColor = applyTint(fragColor);'
|
||||
|
|
32
src/renderer/webgl/shaders/configs/MakeDefineLights.js
Normal file
32
src/renderer/webgl/shaders/configs/MakeDefineLights.js
Normal file
|
@ -0,0 +1,32 @@
|
|||
/**
|
||||
* @author Benjamin D. Richards <benjamindrichards@gmail.com>
|
||||
* @copyright 2013-2024 Phaser Studio Inc.
|
||||
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
||||
*/
|
||||
|
||||
var DefineLights = require('../DefineLights-glsl');
|
||||
|
||||
/**
|
||||
* Return a ShaderAdditionConfig for defining the lights and core lighting
|
||||
* algorithm in the fragment shader.
|
||||
*
|
||||
* @function Phaser.Renderer.WebGL.Shaders.MakeDefineLights
|
||||
* @since 3.90.0
|
||||
*
|
||||
* @param {boolean} [disable=false] - Whether to disable the shader addition on creation.
|
||||
* @returns {Phaser.Types.Renderer.WebGL.ShaderAdditionConfig} The shader addition configuration.
|
||||
*/
|
||||
var MakeDefineLights = function (disable)
|
||||
{
|
||||
return {
|
||||
name: 'DefineLights',
|
||||
additions: {
|
||||
fragmentDefine: '#define LIGHT_COUNT 1',
|
||||
fragmentHeader: DefineLights
|
||||
},
|
||||
tags: [ 'LIGHTING' ],
|
||||
disable: !!disable
|
||||
};
|
||||
};
|
||||
|
||||
module.exports = MakeDefineLights;
|
19
src/renderer/webgl/shaders/configs/MakeDefineTexCount.js
Normal file
19
src/renderer/webgl/shaders/configs/MakeDefineTexCount.js
Normal file
|
@ -0,0 +1,19 @@
|
|||
/**
|
||||
* @author Benjamin D. Richards <benjamindrichards@gmail.com>
|
||||
* @copyright 2013-2024 Phaser Studio Inc.
|
||||
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
||||
*/
|
||||
|
||||
var MakeDefineTexCount = function (maxTextures, disable)
|
||||
{
|
||||
return {
|
||||
name: maxTextures + 'TexCount',
|
||||
additions: {
|
||||
fragmentDefine: '#define TEXTURE_COUNT ' + maxTextures
|
||||
},
|
||||
tags: [ 'TexCount' ],
|
||||
disable: !!disable
|
||||
};
|
||||
};
|
||||
|
||||
module.exports = MakeDefineTexCount;
|
28
src/renderer/webgl/shaders/configs/MakeFlatNormal.js
Normal file
28
src/renderer/webgl/shaders/configs/MakeFlatNormal.js
Normal file
|
@ -0,0 +1,28 @@
|
|||
/**
|
||||
* @author Benjamin D. Richards <benjamindrichards@gmail.com>
|
||||
* @copyright 2013-2024 Phaser Studio Inc.
|
||||
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Return a ShaderAdditionConfig for defining a flat normal.
|
||||
* This is used to light objects without a normal map.
|
||||
*
|
||||
* @function Phaser.Renderer.WebGL.Shaders.MakeFlatNormal
|
||||
* @since 3.90.0
|
||||
* @param {boolean} [disable=false] - Whether to disable the shader addition on creation.
|
||||
* @returns {Phaser.Types.Renderer.WebGL.ShaderAdditionConfig} The shader addition configuration.
|
||||
*/
|
||||
var MakeFlatNormal = function (disable)
|
||||
{
|
||||
return {
|
||||
name: 'FlatNormal',
|
||||
additions: {
|
||||
fragmentProcess: 'vec3 normal = vec3(0.0, 0.0, 1.0);'
|
||||
},
|
||||
tags: [ 'LIGHTING' ],
|
||||
disable: !!disable
|
||||
};
|
||||
};
|
||||
|
||||
module.exports = MakeFlatNormal;
|
31
src/renderer/webgl/shaders/configs/MakeGetNormalFromMap.js
Normal file
31
src/renderer/webgl/shaders/configs/MakeGetNormalFromMap.js
Normal file
|
@ -0,0 +1,31 @@
|
|||
/**
|
||||
* @author Benjamin D. Richards <benjamindrichards@gmail.com>
|
||||
* @copyright 2013-2024 Phaser Studio Inc.
|
||||
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
||||
*/
|
||||
|
||||
var GetNormalFromMap = require('../GetNormalFromMap-glsl');
|
||||
|
||||
/**
|
||||
* Return a ShaderAdditionConfig for creating an outInverseRotationMatrix
|
||||
* in the vertex shader, which is used to apply lighting to a texture.
|
||||
*
|
||||
* @function Phaser.Renderer.WebGL.Shaders.MakeGetNormalFromMap
|
||||
* @since 3.90.0
|
||||
* @param {boolean} [disable=false] - Whether to disable the shader addition on creation.
|
||||
* @returns {Phaser.Types.Renderer.WebGL.ShaderAdditionConfig} The shader addition configuration.
|
||||
*/
|
||||
var MakeGetNormalFromMap = function (disable)
|
||||
{
|
||||
return {
|
||||
name: 'NormalMap',
|
||||
additions: {
|
||||
fragmentHeader: GetNormalFromMap,
|
||||
fragmentProcess: 'vec3 normal = getNormalFromMap(texCoord);'
|
||||
},
|
||||
tags: [ 'LIGHTING' ],
|
||||
disable: !!disable
|
||||
};
|
||||
};
|
||||
|
||||
module.exports = MakeGetNormalFromMap;
|
29
src/renderer/webgl/shaders/configs/MakeGetTexCoordOut.js
Normal file
29
src/renderer/webgl/shaders/configs/MakeGetTexCoordOut.js
Normal file
|
@ -0,0 +1,29 @@
|
|||
/**
|
||||
* @author Benjamin D. Richards <benjamindrichards@gmail.com>
|
||||
* @copyright 2013-2024 Phaser Studio Inc.
|
||||
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Return a ShaderAdditionConfig for getting the texture coordinates
|
||||
* from the vertex shader via the `outTexCoord` variable.
|
||||
*
|
||||
* @function Phaser.Renderer.WebGL.Shaders.MakeGetTexCoordOut
|
||||
* @since 3.90.0
|
||||
*
|
||||
* @param {boolean} [disable=false] - Whether to disable the shader addition on creation.
|
||||
* @returns {Phaser.Types.Renderer.WebGL.ShaderAdditionConfig} The shader addition configuration.
|
||||
*/
|
||||
var MakeGetTexCoordOut = function (disable)
|
||||
{
|
||||
return {
|
||||
name: 'TexCoordOut',
|
||||
additions: {
|
||||
fragmentProcess: 'vec2 texCoord = outTexCoord;\n#pragma phaserTemplate(texCoord)'
|
||||
},
|
||||
tags: [ 'TEXCOORD' ],
|
||||
disable: !!disable
|
||||
};
|
||||
};
|
||||
|
||||
module.exports = MakeGetTexCoordOut;
|
21
src/renderer/webgl/shaders/configs/MakeGetTexRes.js
Normal file
21
src/renderer/webgl/shaders/configs/MakeGetTexRes.js
Normal file
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
* @author Benjamin D. Richards <benjamindrichards@gmail.com>
|
||||
* @copyright 2013-2024 Phaser Studio Inc.
|
||||
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
||||
*/
|
||||
|
||||
var GetTexRes = require('../GetTexRes-glsl');
|
||||
|
||||
var MakeGetTexRes = function (disable)
|
||||
{
|
||||
return {
|
||||
name: 'GetTexRes',
|
||||
additions: {
|
||||
fragmentHeader: GetTexRes
|
||||
},
|
||||
tags: [ 'TEXRES' ],
|
||||
disable: !!disable
|
||||
};
|
||||
};
|
||||
|
||||
module.exports = MakeGetTexRes;
|
|
@ -4,67 +4,15 @@
|
|||
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
||||
*/
|
||||
|
||||
var GetTextureSingle = require('../GetTextureSingle-glsl');
|
||||
var GetTextureMulti = require('../GetTextureMulti-glsl');
|
||||
var GetTexture = require('../GetTexture-glsl');
|
||||
|
||||
/**
|
||||
* Return a ShaderAdditionConfig for getting a texture from a sampler2D.
|
||||
* This maker can return a single texture shader addition
|
||||
* or a multi-texture shader addition, depending on the maxTextures parameter.
|
||||
* The addition will change its name based on the number of textures supported,
|
||||
* so it is tagged with 'TEXTURE' for quick identification at runtime.
|
||||
*
|
||||
* @function Phaser.Renderer.WebGL.Shaders.MakeGetTexture
|
||||
* @since 3.90.0
|
||||
* @param {number} maxTextures - The maximum number of textures to support.
|
||||
* @param {boolean} [disable=false] - Whether to disable the shader addition on creation.
|
||||
* @returns {Phaser.Types.Renderer.WebGL.ShaderAdditionConfig} The shader addition configuration.
|
||||
*/
|
||||
var MakeGetTexture = function (maxTextures, disable)
|
||||
var MakeGetTexture = function (disable)
|
||||
{
|
||||
var fragmentProcess = 'vec4 fragColor = getTexture();';
|
||||
|
||||
if (maxTextures === 1)
|
||||
{
|
||||
return {
|
||||
name: '1TEXTURE',
|
||||
additions: {
|
||||
fragmentHeader: GetTextureSingle,
|
||||
fragmentProcess: fragmentProcess
|
||||
},
|
||||
tags: [ 'TEXTURE' ],
|
||||
disable: !!disable
|
||||
};
|
||||
}
|
||||
|
||||
var src = '';
|
||||
|
||||
for (var i = 0; i < maxTextures; i++)
|
||||
{
|
||||
if (i > 0)
|
||||
{
|
||||
src += '\n\telse ';
|
||||
}
|
||||
|
||||
if (i < maxTextures - 1)
|
||||
{
|
||||
src += 'if (texId < ' + i + '.5)';
|
||||
}
|
||||
|
||||
src += '\n\t{';
|
||||
src += '\n\t\ttexture = texture2D(uMainSampler[' + i + '], texCoord);';
|
||||
src += '\n\t}';
|
||||
}
|
||||
|
||||
return {
|
||||
name: maxTextures + 'TEXTURES',
|
||||
name: 'GetTexture',
|
||||
additions: {
|
||||
fragmentDefine: '#define TEXTURE_COUNT ' + maxTextures,
|
||||
fragmentHeader: GetTextureMulti.replace(
|
||||
'#pragma phaserTemplate(texSamplerProcess)',
|
||||
src
|
||||
),
|
||||
fragmentProcess: fragmentProcess
|
||||
fragmentHeader: GetTexture,
|
||||
fragmentProcess: 'vec4 fragColor = getTexture(texCoord);'
|
||||
},
|
||||
tags: [ 'TEXTURE' ],
|
||||
disable: !!disable
|
||||
|
|
|
@ -5,27 +5,24 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* Returns a ShaderAdditionConfig for wrapping a TileSprite texture.
|
||||
* This makes the texture repeat within the bounds of the TileSprite frame -
|
||||
* it's what makes a TileSprite work.
|
||||
* Returns a ShaderAdditionConfig for providing the vertex shader with the `inFrame` attribute.
|
||||
*
|
||||
* @function Phaser.Renderer.WebGL.Shaders.MakeTileSpriteWrap
|
||||
* @function Phaser.Renderer.WebGL.Shaders.MakeOutFrame
|
||||
* @since 3.90.0
|
||||
* @param {boolean} [disable=false] - Whether to disable the shader addition on creation.
|
||||
* @returns {Phaser.Types.Renderer.WebGL.ShaderAdditionConfig} The shader addition configuration.
|
||||
*/
|
||||
var MakeTileSpriteWrap = function (disable)
|
||||
var MakeOutFrame = function (disable)
|
||||
{
|
||||
return {
|
||||
name: 'TileSpriteWrap',
|
||||
name: 'OutFrame',
|
||||
additions: {
|
||||
vertexHeader: 'attribute vec4 inFrame;',
|
||||
outVariables: 'varying vec4 outFrame;',
|
||||
vertexProcess: 'outFrame = inFrame;',
|
||||
texCoordProcess: '// Wrap texture coordinate into the UV space of the texture frame.\ntexCoord = mod(texCoord, 1.0) * outFrame.zw + outFrame.xy;'
|
||||
outVariables: 'varying vec4 outFrame;',
|
||||
},
|
||||
disable: !!disable
|
||||
};
|
||||
};
|
||||
|
||||
module.exports = MakeTileSpriteWrap;
|
||||
module.exports = MakeOutFrame;
|
35
src/renderer/webgl/shaders/configs/MakeOutInverseRotation.js
Normal file
35
src/renderer/webgl/shaders/configs/MakeOutInverseRotation.js
Normal file
|
@ -0,0 +1,35 @@
|
|||
/**
|
||||
* @author Benjamin D. Richards <benjamindrichards@gmail.com>
|
||||
* @copyright 2013-2024 Phaser Studio Inc.
|
||||
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
||||
*/
|
||||
|
||||
var OutInverseRotation = require('../OutInverseRotation-glsl');
|
||||
|
||||
/**
|
||||
* Return a ShaderAdditionConfig for creating an outInverseRotationMatrix
|
||||
* in the vertex shader, which is used to apply lighting to a texture.
|
||||
*
|
||||
* The `rotation` variable must be available in the vertex renderer.
|
||||
*
|
||||
* @function Phaser.Renderer.WebGL.Shaders.MakeOutInverseRotation
|
||||
* @since 3.90.0
|
||||
*
|
||||
* @param {boolean} [disable=false] - Whether to disable the shader addition on creation.
|
||||
* @returns {Phaser.Types.Renderer.WebGL.ShaderAdditionConfig} The shader addition configuration.
|
||||
*/
|
||||
var MakeOutInverseRotation = function (disable)
|
||||
{
|
||||
return {
|
||||
name: 'OutInverseRotation',
|
||||
additions: {
|
||||
vertexHeader: 'uniform vec4 uCamera;',
|
||||
vertexProcess: OutInverseRotation,
|
||||
outVariables: 'varying mat3 outInverseRotationMatrix;'
|
||||
},
|
||||
tags: [ 'LIGHTING' ],
|
||||
disable: !!disable
|
||||
};
|
||||
};
|
||||
|
||||
module.exports = MakeOutInverseRotation;
|
31
src/renderer/webgl/shaders/configs/MakeSampleNormal.js
Normal file
31
src/renderer/webgl/shaders/configs/MakeSampleNormal.js
Normal file
|
@ -0,0 +1,31 @@
|
|||
/**
|
||||
* @author Benjamin D. Richards <benjamindrichards@gmail.com>
|
||||
* @copyright 2013-2024 Phaser Studio Inc.
|
||||
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Return a ShaderAdditionConfig for sampling a normal map
|
||||
* in the context of a TilemapGPULayer shader.
|
||||
* This shader uses a `Samples` object to collate texture samples.
|
||||
*
|
||||
* @function Phaser.Renderer.WebGL.Shaders.MakeSampleNormal
|
||||
* @since 3.90.0
|
||||
* @param {boolean} [disable=false] - Whether to disable the shader addition on creation.
|
||||
*/
|
||||
var MakeSampleNormal = function (disable)
|
||||
{
|
||||
return {
|
||||
name: 'SampleNormal',
|
||||
additions: {
|
||||
defineSamples: 'vec4 normal;',
|
||||
getSamples: 'samples.normal = texture2D(uNormSampler, texCoord);',
|
||||
mixSamples: 'samples.normal = mix(samples1.normal, samples2.normal, alpha);',
|
||||
declareSamples: 'vec3 normal = normalize(samples.normal.rgb * 2.0 - 1.0);'
|
||||
},
|
||||
tags: ['LIGHTING'],
|
||||
disable: !!disable
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = MakeSampleNormal;
|
22
src/renderer/webgl/shaders/configs/MakeSmoothPixelArt.js
Normal file
22
src/renderer/webgl/shaders/configs/MakeSmoothPixelArt.js
Normal file
|
@ -0,0 +1,22 @@
|
|||
/**
|
||||
* @author Benjamin D. Richards <benjamindrichards@gmail.com>
|
||||
* @copyright 2013-2024 Phaser Studio Inc.
|
||||
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
||||
*/
|
||||
|
||||
var DefineBlockyTexCoord = require('../DefineBlockyTexCoord-glsl');
|
||||
|
||||
var MakeSmoothPixelArt = function (disable)
|
||||
{
|
||||
return {
|
||||
name: 'SmoothPixelArt',
|
||||
additions: {
|
||||
extensions: '#extension GL_OES_standard_derivatives : enable',
|
||||
fragmentHeader: DefineBlockyTexCoord,
|
||||
texCoord: 'texCoord = getBlockyTexCoord(texCoord, getTexRes());'
|
||||
},
|
||||
disable: !!disable
|
||||
};
|
||||
};
|
||||
|
||||
module.exports = MakeSmoothPixelArt;
|
31
src/renderer/webgl/shaders/configs/MakeTexCoordFrameClamp.js
Normal file
31
src/renderer/webgl/shaders/configs/MakeTexCoordFrameClamp.js
Normal file
|
@ -0,0 +1,31 @@
|
|||
/**
|
||||
* @author Benjamin D. Richards <benjamindrichards@gmail.com>
|
||||
* @copyright 2013-2024 Phaser Studio Inc.
|
||||
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
||||
*/
|
||||
|
||||
var DefineTexCoordFrameClamp = require('../DefineTexCoordFrameClamp-glsl');
|
||||
|
||||
/**
|
||||
* Returns a ShaderAdditionConfig for clamping coordinates inside a frame.
|
||||
* This prevents bleeding across the edges of the frame.
|
||||
* However, it creates a hard edge at the frame boundary.
|
||||
*
|
||||
* @function Phaser.Renderer.WebGL.Shaders.MakeTexCoordFrameClamp
|
||||
* @since 3.90.0
|
||||
* @param {boolean} [disable=false] - Whether to disable the shader addition on creation.
|
||||
* @returns {Phaser.Types.Renderer.WebGL.ShaderAdditionConfig} The shader addition configuration.
|
||||
*/
|
||||
var MakeTexCoordFrameClamp = function (disable)
|
||||
{
|
||||
return {
|
||||
name: 'TexCoordFrameClamp',
|
||||
additions: {
|
||||
fragmentHeader: DefineTexCoordFrameClamp,
|
||||
fragmentProcess: 'texCoord = clampTexCoordWithinFrame(texCoord);'
|
||||
},
|
||||
disable: !!disable
|
||||
};
|
||||
};
|
||||
|
||||
module.exports = MakeTexCoordFrameClamp;
|
28
src/renderer/webgl/shaders/configs/MakeTexCoordFrameWrap.js
Normal file
28
src/renderer/webgl/shaders/configs/MakeTexCoordFrameWrap.js
Normal file
|
@ -0,0 +1,28 @@
|
|||
/**
|
||||
* @author Benjamin D. Richards <benjamindrichards@gmail.com>
|
||||
* @copyright 2013-2024 Phaser Studio Inc.
|
||||
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Returns a ShaderAdditionConfig for wrapping coordinates inside a frame.
|
||||
* This makes the texture repeat within the bounds of the frame -
|
||||
* it's what makes a TileSprite work.
|
||||
*
|
||||
* @function Phaser.Renderer.WebGL.Shaders.MakeTexCoordFrameWrap
|
||||
* @since 3.90.0
|
||||
* @param {boolean} [disable=false] - Whether to disable the shader addition on creation.
|
||||
* @returns {Phaser.Types.Renderer.WebGL.ShaderAdditionConfig} The shader addition configuration.
|
||||
*/
|
||||
var MakeTexCoordFrameWrap = function (disable)
|
||||
{
|
||||
return {
|
||||
name: 'TexCoordFrameWrap',
|
||||
additions: {
|
||||
fragmentProcess: '// Wrap texture coordinate into the UV space of the texture frame.\ntexCoord = mod(texCoord, 1.0) * outFrame.zw + outFrame.xy;'
|
||||
},
|
||||
disable: !!disable
|
||||
};
|
||||
};
|
||||
|
||||
module.exports = MakeTexCoordFrameWrap;
|
|
@ -17,6 +17,9 @@ module.exports = {
|
|||
BitmapMaskVert: require('./BitmapMask-vert.js'),
|
||||
ColorMatrixFrag: require('./ColorMatrix-frag.js'),
|
||||
CopyFrag: require('./Copy-frag.js'),
|
||||
DefineBlockyTexCoord: require('./DefineBlockyTexCoord-glsl.js'),
|
||||
DefineLights: require('./DefineLights-glsl.js'),
|
||||
DefineTexCoordFrameClamp: require('./DefineTexCoordFrameClamp-glsl.js'),
|
||||
FXBarrelFrag: require('./FXBarrel-frag.js'),
|
||||
FXBloomFrag: require('./FXBloom-frag.js'),
|
||||
FXBlurHighFrag: require('./FXBlurHigh-frag.js'),
|
||||
|
@ -34,8 +37,9 @@ module.exports = {
|
|||
FXWipeFrag: require('./FXWipe-frag.js'),
|
||||
FlatFrag: require('./Flat-frag.js'),
|
||||
FlatVert: require('./Flat-vert.js'),
|
||||
GetTextureMulti: require('./GetTextureMulti-glsl.js'),
|
||||
GetTextureSingle: require('./GetTextureSingle-glsl.js'),
|
||||
GetNormalFromMap: require('./GetNormalFromMap-glsl.js'),
|
||||
GetTexRes: require('./GetTexRes-glsl.js'),
|
||||
GetTexture: require('./GetTexture-glsl.js'),
|
||||
LightFrag: require('./Light-frag.js'),
|
||||
LinearBlendFrag: require('./LinearBlend-frag.js'),
|
||||
MeshFrag: require('./Mesh-frag.js'),
|
||||
|
@ -44,13 +48,14 @@ module.exports = {
|
|||
MobileVert: require('./Mobile-vert.js'),
|
||||
MultiFrag: require('./Multi-frag.js'),
|
||||
MultiVert: require('./Multi-vert.js'),
|
||||
OutInverseRotation: require('./OutInverseRotation-glsl.js'),
|
||||
PointLightFrag: require('./PointLight-frag.js'),
|
||||
PointLightVert: require('./PointLight-vert.js'),
|
||||
PostFXFrag: require('./PostFX-frag.js'),
|
||||
QuadVert: require('./Quad-vert.js'),
|
||||
SingleFrag: require('./Single-frag.js'),
|
||||
SingleVert: require('./Single-vert.js'),
|
||||
SpriteLayerFrag: require('./SpriteLayer-frag.js'),
|
||||
SpriteLayerVert: require('./SpriteLayer-vert.js')
|
||||
TilemapGPULayerFrag: require('./TilemapGPULayer-frag.js'),
|
||||
TilemapGPULayerVert: require('./TilemapGPULayer-vert.js')
|
||||
|
||||
};
|
||||
|
|
|
@ -1,65 +1,5 @@
|
|||
struct Light
|
||||
vec4 applyLighting (vec4 fragColor, vec3 normal)
|
||||
{
|
||||
vec3 position;
|
||||
vec3 color;
|
||||
float intensity;
|
||||
float radius;
|
||||
};
|
||||
|
||||
// #define LIGHT_COUNT N
|
||||
const int kMaxLights = LIGHT_COUNT;
|
||||
|
||||
uniform vec4 uCamera; /* x, y, rotation, zoom */
|
||||
uniform sampler2D uNormSampler;
|
||||
uniform vec3 uAmbientLightColor;
|
||||
uniform Light uLights[kMaxLights];
|
||||
uniform int uLightCount;
|
||||
#ifdef FEATURE_SELFSHADOW
|
||||
uniform float uDiffuseFlatThreshold;
|
||||
uniform float uPenumbra;
|
||||
#endif
|
||||
|
||||
vec4 applyLighting (vec4 fragColor)
|
||||
{
|
||||
vec3 finalColor = vec3(0.0);
|
||||
#ifdef FEATURE_FLAT_LIGHTING
|
||||
vec3 normal = vec3(0.0, 0.0, 1.0);
|
||||
#else
|
||||
vec2 texCoord = outTexCoord;
|
||||
vec3 normalMap = texture2D(uNormSampler, texCoord).rgb;
|
||||
vec3 normal = normalize(outInverseRotationMatrix * vec3(normalMap * 2.0 - 1.0));
|
||||
#endif
|
||||
vec2 res = vec2(min(uResolution.x, uResolution.y)) * uCamera.w;
|
||||
|
||||
#ifdef FEATURE_SELFSHADOW
|
||||
vec3 unpremultipliedColor = fragColor.rgb / fragColor.a;
|
||||
float occlusionThreshold = 1.0 - ((unpremultipliedColor.r + unpremultipliedColor.g + unpremultipliedColor.b) / uDiffuseFlatThreshold);
|
||||
#endif
|
||||
|
||||
for (int index = 0; index < kMaxLights; ++index)
|
||||
{
|
||||
if (index < uLightCount)
|
||||
{
|
||||
Light light = uLights[index];
|
||||
vec3 lightDir = vec3((light.position.xy / res) - (gl_FragCoord.xy / res), light.position.z / res.x);
|
||||
vec3 lightNormal = normalize(lightDir);
|
||||
float distToSurf = length(lightDir) * uCamera.w;
|
||||
float diffuseFactor = max(dot(normal, lightNormal), 0.0);
|
||||
float radius = (light.radius / res.x * uCamera.w) * uCamera.w;
|
||||
float attenuation = clamp(1.0 - distToSurf * distToSurf / (radius * radius), 0.0, 1.0);
|
||||
#ifdef FEATURE_SELFSHADOW
|
||||
float occluded = smoothstep(0.0, 1.0, (diffuseFactor - occlusionThreshold) / uPenumbra);
|
||||
vec3 diffuse = light.color * diffuseFactor * occluded;
|
||||
#else
|
||||
vec3 diffuse = light.color * diffuseFactor;
|
||||
#endif
|
||||
finalColor += (attenuation * diffuse) * light.intensity;
|
||||
}
|
||||
}
|
||||
|
||||
vec4 colorOutput = vec4(uAmbientLightColor + finalColor, 1.0);
|
||||
|
||||
fragColor *= vec4(colorOutput.rgb * colorOutput.a, colorOutput.a);
|
||||
|
||||
return fragColor;
|
||||
vec4 lighting = getLighting(fragColor, normal);
|
||||
return fragColor * vec4(lighting.rgb * lighting.a, lighting.a);
|
||||
}
|
||||
|
|
12
src/renderer/webgl/shaders/src/DefineBlockyTexCoord.glsl
Normal file
12
src/renderer/webgl/shaders/src/DefineBlockyTexCoord.glsl
Normal file
|
@ -0,0 +1,12 @@
|
|||
// Permutator\'s CC0 antialiased blocky sampling algorithm from https://www.shadertoy.com/view/ltfXWS
|
||||
vec2 v2len (vec2 a, vec2 b)
|
||||
{
|
||||
return sqrt(a*a+b*b);
|
||||
}
|
||||
vec2 getBlockyTexCoord (vec2 texCoord, vec2 texRes) {
|
||||
texCoord *= texRes;
|
||||
vec2 seam = floor(texCoord + 0.5);
|
||||
texCoord = (texCoord - seam) / v2len(dFdx(texCoord), dFdy(texCoord)) + seam;
|
||||
texCoord = clamp(texCoord, seam-.5, seam+.5);
|
||||
return texCoord / texRes;
|
||||
}
|
56
src/renderer/webgl/shaders/src/DefineLights.glsl
Normal file
56
src/renderer/webgl/shaders/src/DefineLights.glsl
Normal file
|
@ -0,0 +1,56 @@
|
|||
struct Light
|
||||
{
|
||||
vec3 position;
|
||||
vec3 color;
|
||||
float intensity;
|
||||
float radius;
|
||||
};
|
||||
|
||||
// #define LIGHT_COUNT N
|
||||
const int kMaxLights = LIGHT_COUNT;
|
||||
|
||||
uniform vec4 uCamera; /* x, y, rotation, zoom */
|
||||
uniform sampler2D uNormSampler;
|
||||
uniform vec3 uAmbientLightColor;
|
||||
uniform Light uLights[kMaxLights];
|
||||
uniform int uLightCount;
|
||||
#ifdef FEATURE_SELFSHADOW
|
||||
uniform float uDiffuseFlatThreshold;
|
||||
uniform float uPenumbra;
|
||||
#endif
|
||||
|
||||
vec4 getLighting (vec4 fragColor, vec3 normal)
|
||||
{
|
||||
vec3 finalColor = vec3(0.0);
|
||||
vec2 res = vec2(min(uResolution.x, uResolution.y)) * uCamera.w;
|
||||
|
||||
#ifdef FEATURE_SELFSHADOW
|
||||
vec3 unpremultipliedColor = fragColor.rgb / fragColor.a;
|
||||
float occlusionThreshold = 1.0 - ((unpremultipliedColor.r + unpremultipliedColor.g + unpremultipliedColor.b) / uDiffuseFlatThreshold);
|
||||
#endif
|
||||
|
||||
for (int index = 0; index < kMaxLights; ++index)
|
||||
{
|
||||
if (index < uLightCount)
|
||||
{
|
||||
Light light = uLights[index];
|
||||
vec3 lightDir = vec3((light.position.xy / res) - (gl_FragCoord.xy / res), light.position.z / res.x);
|
||||
vec3 lightNormal = normalize(lightDir);
|
||||
float distToSurf = length(lightDir) * uCamera.w;
|
||||
float diffuseFactor = max(dot(normal, lightNormal), 0.0);
|
||||
float radius = (light.radius / res.x * uCamera.w) * uCamera.w;
|
||||
float attenuation = clamp(1.0 - distToSurf * distToSurf / (radius * radius), 0.0, 1.0);
|
||||
#ifdef FEATURE_SELFSHADOW
|
||||
float occluded = smoothstep(0.0, 1.0, (diffuseFactor - occlusionThreshold) / uPenumbra);
|
||||
vec3 diffuse = light.color * diffuseFactor * occluded;
|
||||
#else
|
||||
vec3 diffuse = light.color * diffuseFactor;
|
||||
#endif
|
||||
finalColor += (attenuation * diffuse) * light.intensity;
|
||||
}
|
||||
}
|
||||
|
||||
vec4 colorOutput = vec4(uAmbientLightColor + finalColor, 1.0);
|
||||
|
||||
return colorOutput;
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
vec2 clampTexCoordWithinFrame (vec2 texCoord)
|
||||
{
|
||||
vec2 texRes = getTexRes();
|
||||
vec4 frameTexel = outFrame * texRes.xyxy;
|
||||
vec2 frameMin = frameTexel.xy + vec2(0.5, 0.5);
|
||||
vec2 frameMax = frameTexel.xy + frameTexel.zw - vec2(0.5, 0.5);
|
||||
return clamp(texCoord, frameMin / texRes, frameMax / texRes);
|
||||
}
|
|
@ -1,5 +1,7 @@
|
|||
#pragma phaserTemplate(shaderName)
|
||||
|
||||
#pragma phaserTemplate(extensions)
|
||||
|
||||
#pragma phaserTemplate(features)
|
||||
|
||||
#ifdef GL_FRAGMENT_PRECISION_HIGH
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#pragma phaserTemplate(shaderName)
|
||||
|
||||
#pragma phaserTemplate(extensions)
|
||||
|
||||
#pragma phaserTemplate(features)
|
||||
|
||||
precision mediump float;
|
||||
|
|
5
src/renderer/webgl/shaders/src/GetNormalFromMap.glsl
Normal file
5
src/renderer/webgl/shaders/src/GetNormalFromMap.glsl
Normal file
|
@ -0,0 +1,5 @@
|
|||
vec3 getNormalFromMap (vec2 texCoord)
|
||||
{
|
||||
vec3 normalMap = texture2D(uNormSampler, texCoord).rgb;
|
||||
return normalize(outInverseRotationMatrix * vec3(normalMap * 2.0 - 1.0));
|
||||
}
|
24
src/renderer/webgl/shaders/src/GetTexRes.glsl
Normal file
24
src/renderer/webgl/shaders/src/GetTexRes.glsl
Normal file
|
@ -0,0 +1,24 @@
|
|||
// Set elsewhere: `#define TEXTURE_COUNT 1`
|
||||
uniform vec2 uMainResolution[TEXTURE_COUNT];
|
||||
vec2 getTexRes ()
|
||||
{
|
||||
#if TEXTURE_COUNT == 1
|
||||
float texId = 0.0;
|
||||
#else
|
||||
float texId = outTexDatum;
|
||||
#endif
|
||||
#pragma phaserTemplate(texIdProcess)
|
||||
|
||||
vec2 texRes = vec2(0.0);
|
||||
|
||||
for (int i = 0; i < TEXTURE_COUNT; i++)
|
||||
{
|
||||
if (texId == float(i))
|
||||
{
|
||||
texRes = uMainResolution[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return texRes;
|
||||
}
|
24
src/renderer/webgl/shaders/src/GetTexture.glsl
Normal file
24
src/renderer/webgl/shaders/src/GetTexture.glsl
Normal file
|
@ -0,0 +1,24 @@
|
|||
// Set elsewhere: `#define TEXTURE_COUNT 1`
|
||||
uniform sampler2D uMainSampler[TEXTURE_COUNT];
|
||||
vec4 getTexture (vec2 texCoord)
|
||||
{
|
||||
#if TEXTURE_COUNT == 1
|
||||
float texId = 0.0;
|
||||
#else
|
||||
float texId = outTexDatum;
|
||||
#endif
|
||||
#pragma phaserTemplate(texIdProcess)
|
||||
|
||||
vec4 texture = vec4(0.0);
|
||||
|
||||
for (int i = 0; i < TEXTURE_COUNT; i++)
|
||||
{
|
||||
if (texId == float(i))
|
||||
{
|
||||
texture = texture2D(uMainSampler[i], texCoord);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return texture;
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
uniform sampler2D uMainSampler[TEXTURE_COUNT];
|
||||
|
||||
vec4 getTexture ()
|
||||
{
|
||||
float texId = outTexDatum;
|
||||
#pragma phaserTemplate(texIdProcess)
|
||||
vec2 texCoord = outTexCoord;
|
||||
#pragma phaserTemplate(texCoordProcess)
|
||||
|
||||
vec4 texture = vec4(0.0);
|
||||
|
||||
#pragma phaserTemplate(texSamplerProcess)
|
||||
|
||||
return texture;
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
uniform sampler2D uMainSampler;
|
||||
|
||||
vec4 getTexture ()
|
||||
{
|
||||
vec2 texCoord = outTexCoord;
|
||||
#pragma phaserTemplate(texCoordProcess)
|
||||
|
||||
return texture2D(uMainSampler, texCoord);
|
||||
}
|
|
@ -1,5 +1,7 @@
|
|||
#pragma phaserTemplate(shaderName)
|
||||
|
||||
#pragma phaserTemplate(extensions)
|
||||
|
||||
#pragma phaserTemplate(features)
|
||||
|
||||
#ifdef GL_FRAGMENT_PRECISION_HIGH
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#pragma phaserTemplate(shaderName)
|
||||
|
||||
#pragma phaserTemplate(extensions)
|
||||
|
||||
#pragma phaserTemplate(features)
|
||||
|
||||
#ifdef GL_FRAGMENT_PRECISION_HIGH
|
||||
|
|
8
src/renderer/webgl/shaders/src/OutInverseRotation.glsl
Normal file
8
src/renderer/webgl/shaders/src/OutInverseRotation.glsl
Normal file
|
@ -0,0 +1,8 @@
|
|||
float inverseRotation = -rotation - uCamera.z;
|
||||
float irSine = sin(inverseRotation);
|
||||
float irCosine = cos(inverseRotation);
|
||||
outInverseRotationMatrix = mat3(
|
||||
irCosine, irSine, 0.0,
|
||||
-irSine, irCosine, 0.0,
|
||||
0.0, 0.0, 1.0
|
||||
);
|
|
@ -1,5 +1,7 @@
|
|||
#pragma phaserTemplate(shaderName)
|
||||
|
||||
#pragma phaserTemplate(extensions)
|
||||
|
||||
#pragma phaserTemplate(features)
|
||||
|
||||
precision mediump float;
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#pragma phaserTemplate(shaderName)
|
||||
|
||||
#pragma phaserTemplate(extensions)
|
||||
|
||||
#pragma phaserTemplate(features)
|
||||
|
||||
precision mediump float;
|
||||
|
|
303
src/renderer/webgl/shaders/src/TilemapGPULayer.frag
Normal file
303
src/renderer/webgl/shaders/src/TilemapGPULayer.frag
Normal file
|
@ -0,0 +1,303 @@
|
|||
#version 100
|
||||
#pragma phaserTemplate(shaderName)
|
||||
|
||||
#pragma phaserTemplate(extensions)
|
||||
|
||||
#pragma phaserTemplate(features)
|
||||
|
||||
#ifdef GL_FRAGMENT_PRECISION_HIGH
|
||||
precision highp float;
|
||||
#else
|
||||
precision mediump float;
|
||||
#endif
|
||||
|
||||
/* Redefine MAX_ANIM_FRAMES to support animations with different frame numbers. */
|
||||
#define MAX_ANIM_FRAMES 0
|
||||
|
||||
#pragma phaserTemplate(fragmentDefine)
|
||||
|
||||
uniform vec2 uResolution;
|
||||
uniform int roundPixels;
|
||||
uniform sampler2D uMainSampler;
|
||||
uniform sampler2D uLayerSampler;
|
||||
uniform vec2 uMainResolution;
|
||||
uniform vec2 uLayerResolution;
|
||||
uniform float uTileColumns;
|
||||
uniform vec4 uTileWidthHeightMarginSpacing;
|
||||
uniform float uAlpha;
|
||||
uniform float uTime;
|
||||
|
||||
#if MAX_ANIM_FRAMES > 0
|
||||
uniform sampler2D uAnimSampler;
|
||||
uniform vec2 uAnimResolution;
|
||||
#endif
|
||||
|
||||
varying vec2 outTexCoord;
|
||||
varying vec2 outTileStride;
|
||||
|
||||
#pragma phaserTemplate(outVariables)
|
||||
|
||||
// Utility to support smooth pixel art.
|
||||
vec2 getTexRes ()
|
||||
{
|
||||
return uMainResolution;
|
||||
}
|
||||
|
||||
// Convert a vec4 texel to a float.
|
||||
float floatTexel (vec4 texel)
|
||||
{
|
||||
return texel.r * 255.0 + (texel.g * 255.0 * 256.0) + (texel.b * 255.0 * 256.0 * 256.0) + (texel.a * 255.0 * 256.0 * 256.0 * 256.0);
|
||||
}
|
||||
|
||||
struct Tile
|
||||
{
|
||||
float index;
|
||||
vec2 uv; // In texels.
|
||||
#if MAX_ANIM_FRAMES > 0
|
||||
bool animated;
|
||||
#endif
|
||||
bool empty;
|
||||
};
|
||||
|
||||
Tile getLayerData (vec2 coord)
|
||||
{
|
||||
vec2 texelCoord = coord * uLayerResolution;
|
||||
vec2 tile = floor(texelCoord);
|
||||
vec2 uv = fract(texelCoord);
|
||||
|
||||
vec4 texel = texture2D(uLayerSampler, (tile + 0.5) / uLayerResolution) * 255.0;
|
||||
|
||||
float flags = texel.a;
|
||||
|
||||
/* Check for empty tile flag in bit 28. */
|
||||
if (flags == 16.0)
|
||||
{
|
||||
return Tile(
|
||||
0.0,
|
||||
vec2(0.0),
|
||||
#if MAX_ANIM_FRAMES > 0
|
||||
false,
|
||||
#endif
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
/* Bit 31 is flipX. */
|
||||
bool flipX = flags > 127.0;
|
||||
|
||||
/* Bit 30 is flipY. */
|
||||
bool flipY = mod(flags, 128.0) > 63.0;
|
||||
|
||||
#if MAX_ANIM_FRAMES > 0
|
||||
/* Bit 29 is animation. */
|
||||
bool animated = mod(flags, 64.0) > 31.0;
|
||||
#endif
|
||||
|
||||
if (flipX)
|
||||
{
|
||||
uv.x = 1.0 - uv.x;
|
||||
}
|
||||
|
||||
if (flipY)
|
||||
{
|
||||
uv.y = 1.0 - uv.y;
|
||||
}
|
||||
|
||||
float index = texel.r + (texel.g * 256.0) + (texel.b * 256.0 * 256.0);
|
||||
|
||||
return Tile(
|
||||
index,
|
||||
uv * uTileWidthHeightMarginSpacing.xy,
|
||||
#if MAX_ANIM_FRAMES > 0
|
||||
animated,
|
||||
#endif
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
// Returns the texel coordinates of the tile in the main texture.
|
||||
vec2 getFrameCorner (float index)
|
||||
{
|
||||
float x = mod(index, uTileColumns);
|
||||
float y = floor(index / uTileColumns);
|
||||
vec2 xy = vec2(x, y);
|
||||
|
||||
return xy * outTileStride + uTileWidthHeightMarginSpacing.zz;
|
||||
}
|
||||
|
||||
#if MAX_ANIM_FRAMES > 0
|
||||
// Given an animation index, returns the current frame index.
|
||||
float animationIndex (float index)
|
||||
{
|
||||
// Get initial animation data.
|
||||
float animTextureWidth = uAnimResolution.x;
|
||||
vec2 index2D = vec2(mod(index, animTextureWidth), floor(index / animTextureWidth));
|
||||
vec4 animDurationTexel = texture2D(uAnimSampler, (index2D + 0.5) / uAnimResolution);
|
||||
index2D = vec2(mod(index + 1.0, animTextureWidth), floor((index + 1.0) / animTextureWidth));
|
||||
vec4 animIndexTexel = texture2D(uAnimSampler, (index2D + 0.5) / uAnimResolution);
|
||||
|
||||
float animDuration = floatTexel(animDurationTexel);
|
||||
float animIndex = floatTexel(animIndexTexel);
|
||||
|
||||
// Seek the correct frame.
|
||||
float animTime = mod(uTime, animDuration);
|
||||
float animTimeAccum = 0.0;
|
||||
for (int i = 0; i < MAX_ANIM_FRAMES; i++)
|
||||
{
|
||||
index2D = vec2(mod(animIndex, animTextureWidth), floor(animIndex / animTextureWidth));
|
||||
animDurationTexel = texture2D(uAnimSampler, (index2D + 0.5) / uAnimResolution);
|
||||
float frameDuration = floatTexel(animDurationTexel);
|
||||
animTimeAccum += frameDuration;
|
||||
if (animTime <= animTimeAccum)
|
||||
{
|
||||
// Found the frame.
|
||||
break;
|
||||
}
|
||||
|
||||
// Proceed to the next frame, in 2-texel strides.
|
||||
animIndex += 2.0;
|
||||
}
|
||||
// The index is 1 texel over from the duration.
|
||||
animIndex += 1.0;
|
||||
|
||||
// Derive the animation frame index.
|
||||
index2D = vec2(mod(animIndex, animTextureWidth), floor(animIndex / animTextureWidth));
|
||||
animIndexTexel = texture2D(uAnimSampler, (index2D + 0.5) / uAnimResolution);
|
||||
float animFrameIndex = floatTexel(animIndexTexel);
|
||||
|
||||
return animFrameIndex;
|
||||
}
|
||||
#endif
|
||||
|
||||
vec2 getTileTexelCoord (Tile tile)
|
||||
{
|
||||
if (tile.empty)
|
||||
{
|
||||
return vec2(0.0);
|
||||
}
|
||||
float index = tile.index;
|
||||
|
||||
#if MAX_ANIM_FRAMES > 0
|
||||
// Animated tile seek.
|
||||
if (tile.animated)
|
||||
{
|
||||
index = animationIndex(index);
|
||||
}
|
||||
#endif
|
||||
|
||||
vec2 frameCorner = getFrameCorner(index);
|
||||
return frameCorner + tile.uv;
|
||||
}
|
||||
|
||||
#pragma phaserTemplate(fragmentHeader)
|
||||
|
||||
struct Samples {
|
||||
vec4 color;
|
||||
#pragma phaserTemplate(defineSamples)
|
||||
};
|
||||
|
||||
// Get all samples that directly contribute to a given texel color.
|
||||
Samples getColorSamples (vec2 texCoord)
|
||||
{
|
||||
Samples samples;
|
||||
|
||||
samples.color = texture2D(uMainSampler, texCoord);
|
||||
|
||||
#pragma phaserTemplate(getSamples)
|
||||
|
||||
return samples;
|
||||
}
|
||||
|
||||
Samples mixSamples (Samples samples1, Samples samples2, float alpha)
|
||||
{
|
||||
Samples samples;
|
||||
|
||||
samples.color = mix(samples1.color, samples2.color, alpha);
|
||||
|
||||
#pragma phaserTemplate(mixSamples)
|
||||
|
||||
return samples;
|
||||
}
|
||||
|
||||
// Get the set of samples that will be used to calculate the final color of a fragment.
|
||||
Samples getFinalSamples (Tile tile, vec2 layerTexCoord)
|
||||
{
|
||||
vec2 texelCoord = getTileTexelCoord(tile);
|
||||
vec2 texCoord = texelCoord / uMainResolution;
|
||||
#pragma phaserTemplate(texCoord)
|
||||
#ifndef FEATURE_BORDERFILTER
|
||||
return getColorSamples(texCoord);
|
||||
#else
|
||||
#pragma phaserTemplate(finalSamples)
|
||||
vec2 wh = uTileWidthHeightMarginSpacing.xy;
|
||||
vec2 frameCorner = getFrameCorner(tile.index);
|
||||
vec2 frameCornerOpposite = frameCorner + wh;
|
||||
vec2 texCoordClamped = clamp(texCoord, (frameCorner + 0.5) / uMainResolution, (frameCornerOpposite - 0.5) / uMainResolution);
|
||||
vec2 dTexelCoord = (texCoord - texCoordClamped) * uMainResolution;
|
||||
vec2 offsets = sign(dTexelCoord);
|
||||
Samples samples0 = getColorSamples(texCoordClamped);
|
||||
if (offsets.x == 0.0)
|
||||
{
|
||||
if (offsets.y == 0.0)
|
||||
{
|
||||
// No border conditions.
|
||||
return samples0;
|
||||
}
|
||||
// Vertical border condition.
|
||||
Tile tileY = getLayerData(layerTexCoord + (offsets - dTexelCoord) / wh / uLayerResolution);
|
||||
vec2 texelCoordY = getTileTexelCoord(tileY);
|
||||
vec2 texCoordY = texelCoordY / uMainResolution;
|
||||
Samples samplesY = getColorSamples(texCoordY);
|
||||
return mixSamples(samples0, samplesY, abs(dTexelCoord.y));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (offsets.y == 0.0)
|
||||
{
|
||||
// Horizontal border condition.
|
||||
Tile tileX = getLayerData(layerTexCoord + (offsets - dTexelCoord) / wh / uLayerResolution);
|
||||
vec2 texelCoordX = getTileTexelCoord(tileX);
|
||||
vec2 texCoordX = texelCoordX / uMainResolution;
|
||||
Samples samplesX = getColorSamples(texCoordX);
|
||||
return mixSamples(samples0, samplesX, abs(dTexelCoord.x));
|
||||
}
|
||||
// Corner border condition.
|
||||
Tile tileX = getLayerData(layerTexCoord + (offsets * vec2(1.0, 0.0) - dTexelCoord) / wh / uLayerResolution);
|
||||
vec2 texelCoordX = getTileTexelCoord(tileX);
|
||||
vec2 texCoordX = texelCoordX / uMainResolution;
|
||||
Samples samplesX = getColorSamples(texCoordX);
|
||||
|
||||
Tile tileY = getLayerData(layerTexCoord + (offsets * vec2(0.0, 1.0) - dTexelCoord) / wh / uLayerResolution);
|
||||
vec2 texelCoordY = getTileTexelCoord(tileY);
|
||||
vec2 texCoordY = texelCoordY / uMainResolution;
|
||||
Samples samplesY = getColorSamples(texCoordY);
|
||||
|
||||
Tile tileXY = getLayerData(layerTexCoord + (offsets - dTexelCoord) / wh / uLayerResolution);
|
||||
vec2 texelCoordXY = getTileTexelCoord(tileXY);
|
||||
vec2 texCoordXY = texelCoordXY / uMainResolution;
|
||||
Samples samplesXY = getColorSamples(texCoordXY);
|
||||
|
||||
// Mix the samples.
|
||||
Samples samples1 = mixSamples(samples0, samplesX, abs(dTexelCoord.x));
|
||||
Samples samples2 = mixSamples(samplesY, samplesXY, abs(dTexelCoord.x));
|
||||
return mixSamples(samples1, samples2, abs(dTexelCoord.y));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void main ()
|
||||
{
|
||||
vec2 layerTexCoord = outTexCoord;
|
||||
Tile tile = getLayerData(layerTexCoord);
|
||||
|
||||
Samples samples = getFinalSamples(tile, layerTexCoord);
|
||||
|
||||
vec4 fragColor = samples.color;
|
||||
#pragma phaserTemplate(declareSamples)
|
||||
|
||||
#pragma phaserTemplate(fragmentProcess)
|
||||
|
||||
fragColor *= uAlpha;
|
||||
|
||||
gl_FragColor = fragColor;
|
||||
}
|
43
src/renderer/webgl/shaders/src/TilemapGPULayer.vert
Normal file
43
src/renderer/webgl/shaders/src/TilemapGPULayer.vert
Normal file
|
@ -0,0 +1,43 @@
|
|||
#pragma phaserTemplate(shaderName)
|
||||
|
||||
#pragma phaserTemplate(extensions)
|
||||
|
||||
#pragma phaserTemplate(features)
|
||||
|
||||
#ifdef GL_FRAGMENT_PRECISION_HIGH
|
||||
precision highp float;
|
||||
#else
|
||||
precision mediump float;
|
||||
#endif
|
||||
|
||||
#pragma phaserTemplate(vertexDefine)
|
||||
|
||||
uniform mat4 uProjectionMatrix;
|
||||
uniform int uRoundPixels;
|
||||
uniform vec2 uResolution;
|
||||
uniform vec4 uTileWidthHeightMarginSpacing;
|
||||
|
||||
attribute vec2 inPosition;
|
||||
attribute vec2 inTexCoord;
|
||||
|
||||
varying vec2 outTexCoord;
|
||||
varying vec2 outTileStride;
|
||||
|
||||
#pragma phaserTemplate(outVariables)
|
||||
|
||||
#pragma phaserTemplate(vertexHeader)
|
||||
|
||||
void main ()
|
||||
{
|
||||
gl_Position = uProjectionMatrix * vec4(inPosition, 1.0, 1.0);
|
||||
|
||||
if (uRoundPixels == 1)
|
||||
{
|
||||
gl_Position.xy = floor(((gl_Position.xy + 1.0) * 0.5 * uResolution) + 0.5) / uResolution * 2.0 - 1.0;
|
||||
}
|
||||
|
||||
outTexCoord = inTexCoord;
|
||||
outTileStride = uTileWidthHeightMarginSpacing.xy + uTileWidthHeightMarginSpacing.zz;
|
||||
|
||||
#pragma phaserTemplate(vertexProcess)
|
||||
}
|
|
@ -17,6 +17,8 @@ var SpliceOne = require('../utils/array/SpliceOne');
|
|||
var Sprite = require('../gameobjects/sprite/Sprite');
|
||||
var Tile = require('./Tile');
|
||||
var TilemapComponents = require('./components');
|
||||
var TilemapLayerBase = require('./TilemapLayerBase');
|
||||
var TilemapGPULayer = require('./TilemapGPULayer');
|
||||
var TilemapLayer = require('./TilemapLayer');
|
||||
var Tileset = require('./Tileset');
|
||||
|
||||
|
@ -579,10 +581,11 @@ var Tilemap = new Class({
|
|||
* @param {(string|string[]|Phaser.Tilemaps.Tileset|Phaser.Tilemaps.Tileset[])} tileset - The tileset, or an array of tilesets, used to render this layer. Can be a string or a Tileset object.
|
||||
* @param {number} [x=0] - The x position to place the layer in the world. If not specified, it will default to the layer offset from Tiled or 0.
|
||||
* @param {number} [y=0] - The y position to place the layer in the world. If not specified, it will default to the layer offset from Tiled or 0.
|
||||
* @param {boolean} [gpu=false] - Create a TilemapGPULayer instead of a TilemapLayer. This option is WebGL-only. A TilemapGPULayer is less flexible, but can be much faster.
|
||||
*
|
||||
* @return {?Phaser.Tilemaps.TilemapLayer} Returns the new layer was created, or null if it failed.
|
||||
* @return {?Phaser.Tilemaps.TilemapLayer|?Phaser.Tilemaps.TilemapGPULayer} Returns the new layer was created, or null if it failed.
|
||||
*/
|
||||
createLayer: function (layerID, tileset, x, y)
|
||||
createLayer: function (layerID, tileset, x, y, gpu)
|
||||
{
|
||||
var index = this.getLayerIndex(layerID);
|
||||
|
||||
|
@ -621,9 +624,19 @@ var Tilemap = new Class({
|
|||
y = layerData.y;
|
||||
}
|
||||
|
||||
var layer = new TilemapLayer(this.scene, this, index, tileset, x, y);
|
||||
var layer;
|
||||
|
||||
if (gpu)
|
||||
{
|
||||
layer = new TilemapGPULayer(this.scene, this, index, tileset, x, y);
|
||||
}
|
||||
else
|
||||
{
|
||||
layer = new TilemapLayer(this.scene, this, index, tileset, x, y);
|
||||
|
||||
layer.setRenderOrder(this.renderOrder);
|
||||
}
|
||||
|
||||
layer.setRenderOrder(this.renderOrder);
|
||||
|
||||
this.scene.sys.displayList.add(layer);
|
||||
|
||||
|
@ -1316,7 +1329,7 @@ var Tilemap = new Class({
|
|||
{
|
||||
return layer;
|
||||
}
|
||||
else if (layer instanceof TilemapLayer && layer.tilemap === this)
|
||||
else if (layer instanceof TilemapLayerBase && layer.tilemap === this)
|
||||
{
|
||||
return layer.layerIndex;
|
||||
}
|
||||
|
|
234
src/tilemaps/TilemapGPULayer.js
Normal file
234
src/tilemaps/TilemapGPULayer.js
Normal file
|
@ -0,0 +1,234 @@
|
|||
/**
|
||||
* @author Benjamin D. Richards <benjamindrichards@gmail.com>
|
||||
* @copyright 2013-2024 Phaser Studio Inc.
|
||||
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
||||
*/
|
||||
|
||||
var DefaultTilemapGPULayerNodes = require('../renderer/webgl/renderNodes/defaults/DefaultTilemapGPULayerNodes');
|
||||
var Class = require('../utils/Class');
|
||||
var TilemapLayerBase = require('./TilemapLayerBase');
|
||||
var TilemapGPULayerRender = require('./TilemapGPULayerRender');
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* A TilemapGPULayer is a special kind of Game Object that renders LayerData from a Tilemap.
|
||||
* Unlike the more flexible TilemapLayer, this object uses a single Tileset
|
||||
* and is optimized for speed and quality over flexibility.
|
||||
* Use it for high-performance rendering of tilemaps which don't update
|
||||
* their contents. It still supports tile animation and flip.
|
||||
*
|
||||
* Performance of this layer can be highly variable.
|
||||
* It is almost entirely GPU-bound, so it will free up CPU resources
|
||||
* for other game code (the CPU usually does much more work than the GPU in games).
|
||||
* It has a fixed cost per pixel on screen, whether there is anything in that
|
||||
* tile or not.
|
||||
* In general, it suffers no performance loss when many tiles are visible,
|
||||
* which can make it superior to TilemapLayer.
|
||||
* However, while it can be many times faster on desktop devices,
|
||||
* mobile devices may struggle due to fillrate and texture sampling issues.
|
||||
* You may want to check `game.device.os.desktop`,
|
||||
* and review whether you want to improve CPU performance,
|
||||
* before deciding to use this layer.
|
||||
*
|
||||
* Create a TilemapGPULayer by adding the `gpu` flag to a call to
|
||||
* `Tilemap.createLayer()`. This will return a TilemapGPULayer instance.
|
||||
*
|
||||
* This layer has the following abilities and restrictions:
|
||||
*
|
||||
* - Use a single tileset, with a single texture image.
|
||||
* - Maximum tilemap size of 4096x4096 tiles.
|
||||
* - Maximum of 2^23 (8388608) unique tile IDs.
|
||||
* - Tiles may be flipped.
|
||||
* - Tiles may be animated.
|
||||
* - Animation data limit of 8388608 entries (each animation or each frame of animation uses one entry).
|
||||
* - Orthographic tilemaps only.
|
||||
*
|
||||
* The layer renders via a special shader.
|
||||
* This uses a texture containing the layer tile data, and a second texture
|
||||
* containing any tile animations. The shader then renders the tiles
|
||||
* as a single quad. Because it doesn't have to compute individual tiles
|
||||
* on the CPU, this is much faster than a TilemapLayer.
|
||||
* However, because it treats tiles as a single orthographic grid,
|
||||
* it is not suitable for use with isometric or hexagonal tilemaps,
|
||||
* or other types of tilemap that require different rendering methods.
|
||||
*
|
||||
* If the tileset image uses NEAREST minfiltering, the shader will render
|
||||
* sharp edged pixels. Otherwise, it assumes LINEAR filtering.
|
||||
* The shader will automatically render smooth borders between tiles
|
||||
* in LINEAR mode, with no seams or bleeding, for perfect results.
|
||||
* A regular TilemapLayer cannot render smooth borders like this,
|
||||
* creating sharp seams between tiles.
|
||||
*
|
||||
* The layer can be edited, but it will not update automatically.
|
||||
* Regenerate the layer tile data texture by calling `generateLayerDataTexture`.
|
||||
*
|
||||
* @class TilemapGPULayer
|
||||
* @extends Phaser.Tilemaps.TilemapLayerBase
|
||||
* @memberof Phaser.Tilemaps
|
||||
* @constructor
|
||||
* @since 3.90.0
|
||||
*
|
||||
* @param {Phaser.Scene} scene - The Scene to which this TilemapGPULayer belongs.
|
||||
* @param {Phaser.Tilemaps.Tilemap} tilemap - The Tilemap this layer is a part of.
|
||||
* @param {number} layerIndex - The index of the LayerData associated with this layer.
|
||||
* @param {(string|Phaser.Tilemaps.Tileset)} tileset - The tileset used to render the tiles in this layer. Can be a string or a Tileset object.
|
||||
* @param {number} [x] - The world x position where the top left of this layer will be placed.
|
||||
* @param {number} [y] - The world y position where the top left of this layer will be placed.
|
||||
*/
|
||||
var TilemapGPULayer = new Class({
|
||||
Extends: TilemapLayerBase,
|
||||
|
||||
Mixins: [
|
||||
TilemapGPULayerRender
|
||||
],
|
||||
|
||||
initialize: function TilemapGPULayer (scene, tilemap, layerIndex, tileset, x, y)
|
||||
{
|
||||
TilemapLayerBase.call(this, 'TilemapGPULayer', scene, tilemap, layerIndex, x, y);
|
||||
|
||||
/**
|
||||
* The `Tileset` associated with this layer.
|
||||
*
|
||||
* Unlike a `TilemapLayer`, this object can only have one tileset,
|
||||
* because the renderer is optimized for a single texture.
|
||||
*
|
||||
* @name Phaser.Tilemaps.TilemapGPULayer#tileset
|
||||
* @type {Phaser.Tilemaps.Tileset}
|
||||
* @since 3.50.0
|
||||
*/
|
||||
this.tileset = null;
|
||||
|
||||
/**
|
||||
* A texture containing the tile data for this game object.
|
||||
* Each texel describes a single tile in the layer.
|
||||
*
|
||||
* Each texel is stored as a 32-bit value, encoded thus:
|
||||
*
|
||||
* - 1 bit: Horizontal flip flag.
|
||||
* - 1 bit: Vertical flip flag.
|
||||
* - 1 bit: Animation flag.
|
||||
* - 1 bit: Unused.
|
||||
* - 28 bits: Tile index.
|
||||
*
|
||||
* @name Phaser.Tilemaps.TilemapGPULayer#layerDataTexture
|
||||
* @type {Phaser.Renderer.WebGL.WebGLTextureWrapper}
|
||||
* @since 3.90.0
|
||||
*/
|
||||
this.layerDataTexture = null;
|
||||
|
||||
this.setTileset(tileset);
|
||||
|
||||
this.initRenderNodes(this._defaultRenderNodesMap);
|
||||
},
|
||||
|
||||
/**
|
||||
* The default render nodes for this Game Object.
|
||||
*
|
||||
* @name Phaser.Tilemaps.TilemapGPULayer#_defaultRenderNodesMap
|
||||
* @type {Map<string, string>}
|
||||
* @private
|
||||
* @webglOnly
|
||||
* @readonly
|
||||
* @since 3.90.0
|
||||
*/
|
||||
_defaultRenderNodesMap: {
|
||||
get: function ()
|
||||
{
|
||||
return DefaultTilemapGPULayerNodes;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Populates data structures to render this tilemap layer.
|
||||
*
|
||||
* @method Phaser.Tilemaps.TilemapGPULayer#setTileset
|
||||
* @private
|
||||
* @since 3.90.0
|
||||
*
|
||||
* @param {(string|Phaser.Tilemaps.Tileset)} tileset - The tileset used to render this layer. Can be a string or a Tileset object.
|
||||
*/
|
||||
setTileset: function (tileset)
|
||||
{
|
||||
if (typeof tileset === 'string')
|
||||
{
|
||||
tileset = this.tilemap.getTileset(tileset);
|
||||
}
|
||||
|
||||
this.tileset = tileset;
|
||||
|
||||
// Convert layer into a data texture.
|
||||
this.generateLayerDataTexture();
|
||||
},
|
||||
|
||||
/**
|
||||
* Generate the data textures for this game object.
|
||||
* This method is called internally by `setTileset`.
|
||||
*
|
||||
* @method Phaser.Tilemaps.TilemapGPULayer#generateLayerDataTexture
|
||||
* @since 3.90.0
|
||||
*/
|
||||
generateLayerDataTexture: function ()
|
||||
{
|
||||
var layer = this.layer;
|
||||
var tileset = this.tileset;
|
||||
var firstgid = tileset.firstgid;
|
||||
var renderer = this.scene.renderer;
|
||||
|
||||
// Get or initialize the animation data texture in the Tileset.
|
||||
var indexToAnimMap = tileset.getAnimationDataIndexMap(renderer);
|
||||
|
||||
// Generate the layer map.
|
||||
var u32 = new Uint32Array(layer.width * layer.height);
|
||||
for (var y = 0; y < layer.height; y++)
|
||||
{
|
||||
for (var x = 0; x < layer.width; x++)
|
||||
{
|
||||
var tile = layer.data[y][x];
|
||||
|
||||
var index = tile.index - firstgid;
|
||||
|
||||
var flipX = tile.flipX;
|
||||
var flipY = tile.flipY;
|
||||
var animated = false;
|
||||
|
||||
if (indexToAnimMap.has(index))
|
||||
{
|
||||
// This tile is part of an animation.
|
||||
index = indexToAnimMap.get(index);
|
||||
animated = true;
|
||||
}
|
||||
|
||||
// Set flip flags.
|
||||
if (flipX)
|
||||
{
|
||||
index |= 0x80000000;
|
||||
}
|
||||
if (flipY)
|
||||
{
|
||||
index |= 0x40000000;
|
||||
}
|
||||
if (animated)
|
||||
{
|
||||
index |= 0x20000000;
|
||||
}
|
||||
if (tile.index === -1)
|
||||
{
|
||||
// Set the fourth bit to 1 to indicate an empty tile.
|
||||
index = 0x10000000;
|
||||
}
|
||||
|
||||
u32[y * layer.width + x] = index;
|
||||
}
|
||||
}
|
||||
|
||||
// Create or update the tile data texture.
|
||||
if (this.layerDataTexture)
|
||||
{
|
||||
this.layerDataTexture.destroy();
|
||||
}
|
||||
var u8 = new Uint8Array(u32.buffer);
|
||||
this.layerDataTexture = renderer.createUint8ArrayTexture(u8, layer.width, layer.height, false);
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = TilemapGPULayer;
|
21
src/tilemaps/TilemapGPULayerRender.js
Normal file
21
src/tilemaps/TilemapGPULayerRender.js
Normal file
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
* @author Benjamin D. Richards <benjamindrichards@gmail.com>
|
||||
* @copyright 2013-2024 Phaser Studio Inc.
|
||||
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
||||
*/
|
||||
|
||||
var NOOP = require('../utils/NOOP');
|
||||
var renderWebGL = NOOP;
|
||||
var renderCanvas = NOOP;
|
||||
|
||||
if (typeof WEBGL_RENDERER)
|
||||
{
|
||||
renderWebGL = require('./TilemapGPULayerWebGLRenderer');
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
|
||||
renderWebGL: renderWebGL,
|
||||
renderCanvas: renderCanvas
|
||||
|
||||
};
|
30
src/tilemaps/TilemapGPULayerWebGLRenderer.js
Normal file
30
src/tilemaps/TilemapGPULayerWebGLRenderer.js
Normal file
|
@ -0,0 +1,30 @@
|
|||
/**
|
||||
* @author Benjamin D. Richards <benjamindrichards@gmail.com>
|
||||
* @copyright 2013-2024 Phaser Studio Inc.
|
||||
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Renders this Game Object with the WebGL Renderer to the given Camera.
|
||||
* The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera.
|
||||
* This method should not be called directly. It is a utility function of the Render module.
|
||||
*
|
||||
* @method Phaser.Tilemaps.TilemapLayer#renderWebGL
|
||||
* @since 3.0.0
|
||||
* @private
|
||||
*
|
||||
* @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - A reference to the current active WebGL renderer.
|
||||
* @param {Phaser.Tilemaps.TilemapLayer} src - The Game Object being rendered in this call.
|
||||
* @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context.
|
||||
*/
|
||||
var TilemapLayerWebGLRenderer = function (renderer, src, drawingContext)
|
||||
{
|
||||
var submitterNode = src.customRenderNodes.Submitter || src.defaultRenderNodes.Submitter;
|
||||
|
||||
submitterNode.run(
|
||||
drawingContext,
|
||||
src
|
||||
);
|
||||
};
|
||||
|
||||
module.exports = TilemapLayerWebGLRenderer;
|
File diff suppressed because it is too large
Load diff
1195
src/tilemaps/TilemapLayerBase.js
Normal file
1195
src/tilemaps/TilemapLayerBase.js
Normal file
File diff suppressed because it is too large
Load diff
|
@ -4,6 +4,7 @@
|
|||
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
||||
*/
|
||||
|
||||
var Map = require('../structs/Map');
|
||||
var Class = require('../utils/Class');
|
||||
var Vector2 = require('../math/Vector2');
|
||||
|
||||
|
@ -208,6 +209,49 @@ var Tileset = new Class({
|
|||
* @default 64
|
||||
*/
|
||||
this.animationSearchThreshold = 64;
|
||||
|
||||
/**
|
||||
* The maximum length of any animation in this tileset, in frames.
|
||||
* This is used internally to optimize rendering.
|
||||
* It is updated when `createAnimationDataTexture` is called.
|
||||
*
|
||||
* @name Phaser.Tilemaps.Tileset#maxAnimationLength
|
||||
* @type {number}
|
||||
* @readonly
|
||||
* @since 3.90.0
|
||||
*/
|
||||
this.maxAnimationLength = 0;
|
||||
|
||||
/**
|
||||
* The texture containing the animation data for this tileset, if any.
|
||||
* This is used by `TilemapGPULayer` to animate tiles.
|
||||
*
|
||||
* This will be created when `createAnimationDataTexture` is called.
|
||||
* Once created, it will be updated when `updateTileData` is called.
|
||||
*
|
||||
* Each texel stores a 32-bit number.
|
||||
* The first set of texels consists of pairs of numbers,
|
||||
* describing the total duration and starting index of an animation.
|
||||
* The second set of texels are the targets of these indices, also in pairs,
|
||||
* describing the duration and actual index of each frame in the animation.
|
||||
*
|
||||
* @name Phaser.Tilemaps.Tileset#_animationDataTexture
|
||||
* @type {?Phaser.Renderer.WebGL.WebGLTextureWrapper}
|
||||
* @private
|
||||
*/
|
||||
this._animationDataTexture = null;
|
||||
|
||||
/**
|
||||
* The map from tile index to animation data index.
|
||||
* This is used to quickly find the animation data for a tile.
|
||||
* This is created when `createAnimationDataTexture` is called.
|
||||
* Once created, it will be updated when `updateTileData` is called.
|
||||
*
|
||||
* @name Phaser.Tilemaps.Tileset#_animationDataIndexMap
|
||||
* @type {?Map<number, number>}
|
||||
* @private
|
||||
*/
|
||||
this._animationDataIndexMap = null;
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -491,7 +535,148 @@ var Tileset = new Class({
|
|||
ty += this.tileHeight + this.tileSpacing;
|
||||
}
|
||||
|
||||
// Update the animation data texture.
|
||||
if (this._animationDataTexture)
|
||||
{
|
||||
this.createAnimationDataTexture();
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get or create the texture containing the animation data for this tileset.
|
||||
* This is used by `TilemapGPULayer` to animate tiles.
|
||||
*
|
||||
* @method Phaser.Tilemaps.Tileset#getAnimationDataTexture
|
||||
* @since 3.90.0
|
||||
* @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - The renderer to use.
|
||||
* @return {Phaser.Renderer.WebGL.WebGLTextureWrapper} The animation data texture.
|
||||
*/
|
||||
getAnimationDataTexture: function (renderer)
|
||||
{
|
||||
if (!this._animationDataTexture)
|
||||
{
|
||||
this.createAnimationDataTexture(renderer);
|
||||
}
|
||||
|
||||
return this._animationDataTexture;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get or create the map from tile index to animation data index.
|
||||
* This is used by `TilemapGPULayer` to animate tiles.
|
||||
*
|
||||
* @method Phaser.Tilemaps.Tileset#getAnimationDataIndexMap
|
||||
* @since 3.90.0
|
||||
* @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - The renderer to use.
|
||||
* @return {Map<number, number>} The map from tile index to animation data index.
|
||||
*/
|
||||
getAnimationDataIndexMap: function (renderer)
|
||||
{
|
||||
if (!this._animationDataIndexMap)
|
||||
{
|
||||
this.createAnimationDataTexture(renderer);
|
||||
}
|
||||
|
||||
return this._animationDataIndexMap;
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates a new WebGLTexture for the tileset's animation data.
|
||||
*
|
||||
* @method Phaser.Tilemaps.Tileset#createAnimationDataTexture
|
||||
* @since 3.90.0
|
||||
*
|
||||
* @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - The renderer to use.
|
||||
*
|
||||
* @return {Phaser.Renderer.WebGL.WebGLTextureWrapper} The new WebGLTexture.
|
||||
*/
|
||||
createAnimationDataTexture: function (renderer)
|
||||
{
|
||||
var tileData = this.tileData;
|
||||
var total = this.total;
|
||||
|
||||
var animations = [];
|
||||
var animFrames = [];
|
||||
var indexToAnimMap = new Map();
|
||||
|
||||
var maxLength = 0;
|
||||
|
||||
for (var i = 0; i < total; i++)
|
||||
{
|
||||
var tileDatum = tileData[i];
|
||||
|
||||
if (tileDatum && tileDatum.animation)
|
||||
{
|
||||
var animation = tileDatum.animation;
|
||||
var animationDuration = tileDatum.animationDuration;
|
||||
|
||||
// This index maps to an animation, not a single tile.
|
||||
indexToAnimMap.set(i, animations.length);
|
||||
|
||||
// This animation points to a run of frames.
|
||||
animations.push([ animationDuration, animFrames.length ]);
|
||||
|
||||
// The run of frames stores the duration and the actual index.
|
||||
for (var j = 0; j < animation.length; j++)
|
||||
{
|
||||
var frame = animation[j];
|
||||
animFrames.push([ frame.duration, frame.tileid ]);
|
||||
}
|
||||
|
||||
// Store the maximum length of any animation.
|
||||
maxLength = Math.max(maxLength, animation.length);
|
||||
}
|
||||
}
|
||||
|
||||
var totalTuples = animations.length + animFrames.length;
|
||||
|
||||
if (totalTuples > 4096 * 4096 / 2)
|
||||
{
|
||||
throw new Error('Tileset.animationDataTexture: too many animations - total number of animations plus animation frames is max 8388608, got ' + (totalTuples));
|
||||
}
|
||||
|
||||
var size = totalTuples * 2;
|
||||
var width = Math.min(size, 4096);
|
||||
var height = Math.ceil(size / 4096);
|
||||
|
||||
var u32 = new Uint32Array(width * height);
|
||||
var offset = 0;
|
||||
|
||||
var animLen = animations.length;
|
||||
|
||||
for (i = 0; i < animLen; i++)
|
||||
{
|
||||
animation = animations[i];
|
||||
var duration = animation[0];
|
||||
var index = animation[1];
|
||||
u32[offset++] = duration;
|
||||
|
||||
// Store the index as an offset from the start of the animation frames.
|
||||
// Double the index to account for the 2x 32-bit values per entry.
|
||||
u32[offset++] = (index + animLen) * 2;
|
||||
}
|
||||
|
||||
for (i = 0; i < animFrames.length; i++)
|
||||
{
|
||||
frame = animFrames[i];
|
||||
var frameDuration = frame[0];
|
||||
var frameIndex = frame[1];
|
||||
u32[offset++] = frameDuration;
|
||||
u32[offset++] = frameIndex;
|
||||
}
|
||||
|
||||
// Create or update the animation data texture.
|
||||
if (this.animationDataTexture)
|
||||
{
|
||||
this.animationDataTexture.destroy();
|
||||
}
|
||||
|
||||
var u8 = new Uint8Array(u32.buffer);
|
||||
this._animationDataTexture = renderer.createUint8ArrayTexture(u8, width, height, false);
|
||||
this._animationDataIndexMap = indexToAnimMap;
|
||||
this.maxAnimationLength = maxLength;
|
||||
}
|
||||
|
||||
});
|
||||
|
|
|
@ -29,7 +29,9 @@ var Tilemaps = {
|
|||
TilemapCreator: require('./TilemapCreator'),
|
||||
TilemapFactory: require('./TilemapFactory'),
|
||||
Tileset: require('./Tileset'),
|
||||
TilemapLayerBase: require('./TilemapLayerBase'),
|
||||
TilemapLayer: require('./TilemapLayer'),
|
||||
TilemapGPULayer: require('./TilemapGPULayer'),
|
||||
Orientation: require('./const/ORIENTATION_CONST'),
|
||||
|
||||
LayerData: require('./mapdata/LayerData'),
|
||||
|
|
Loading…
Reference in a new issue