mirror of
https://github.com/photonstorm/phaser
synced 2024-11-22 20:53:39 +00:00
Make render nodes customizable.
Game objects can now change their render node, in place of a pipeline. Render nodes can be created with custom values, to change their behavior or relationships. Several nodes are renamed. Program Wrapper now supports defining layouts with strings instead of GLenums, to facilitate render node customization.
This commit is contained in:
parent
9940554eba
commit
7e16caeed7
27 changed files with 1071 additions and 634 deletions
206
src/gameobjects/components/RenderNode.js
Normal file
206
src/gameobjects/components/RenderNode.js
Normal file
|
@ -0,0 +1,206 @@
|
|||
/**
|
||||
* @author Benjamin D. Richards <benjamindrichards@gmail.com>
|
||||
* @copyright 2013-2024 Phaser Studio Inc.
|
||||
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
||||
*/
|
||||
|
||||
var DeepCopy = require('../../utils/object/DeepCopy');
|
||||
|
||||
/**
|
||||
* Provides methods for setting the WebGL render node of a Game Object.
|
||||
*
|
||||
* @namespace Phaser.GameObjects.Components.RenderNode
|
||||
* @webglOnly
|
||||
* @since 3.90.0
|
||||
*/
|
||||
var RenderNode = {
|
||||
|
||||
/**
|
||||
* The initial WebGL render node of this Game Object.
|
||||
*
|
||||
* If you call `resetRenderNode` on this Game Object,
|
||||
* the render node is reset to this default.
|
||||
*
|
||||
* @name Phaser.GameObjects.Components.RenderNode#defaultRenderNode
|
||||
* @type {Phaser.Renderer.WebGL.RenderNodes.RenderNode}
|
||||
* @default null
|
||||
* @webglOnly
|
||||
* @since 3.90.0
|
||||
*/
|
||||
defaultRenderNode: null,
|
||||
|
||||
/**
|
||||
* The current WebGL render node of this Game Object.
|
||||
*
|
||||
* @name Phaser.GameObjects.Components.RenderNode#renderNode
|
||||
* @type {Phaser.Renderer.WebGL.RenderNodes.RenderNode}
|
||||
* @default null
|
||||
* @webglOnly
|
||||
* @since 3.90.0
|
||||
*/
|
||||
renderNode: null,
|
||||
|
||||
/**
|
||||
* An object to store render node specific data in, to be read by the render nodes this Game Object uses.
|
||||
*
|
||||
* @name Phaser.GameObjects.Components.RenderNode#renderNodeData
|
||||
* @type {object}
|
||||
* @webglOnly
|
||||
* @since 3.90.0
|
||||
*/
|
||||
renderNodeData: null,
|
||||
|
||||
/**
|
||||
* Sets the initial WebGL render node of this Game Object.
|
||||
*
|
||||
* This should only be called during the instantiation of the Game Object. After that, use `setRenderNode`.
|
||||
*
|
||||
* @method Phaser.GameObjects.Components.RenderNode#initRenderNode
|
||||
* @webglOnly
|
||||
* @since 3.90.0
|
||||
* @param {string|Phaser.Renderer.WebGL.RenderNodes.RenderNode} renderNode - The render node to set on this Game Object. Either a string, or a RenderNode instance.
|
||||
* @return {boolean} `true` if the render node was set successfully, otherwise `false`.
|
||||
*/
|
||||
initRenderNode: function (renderNode)
|
||||
{
|
||||
this.pipelineData = {};
|
||||
|
||||
var renderer = this.scene.sys.renderer;
|
||||
|
||||
if (!renderer)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var manager = renderer.renderNodes;
|
||||
|
||||
if (!manager)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (typeof renderNode === 'string')
|
||||
{
|
||||
renderNode = manager.getNode(renderNode);
|
||||
}
|
||||
if (!renderNode)
|
||||
{
|
||||
renderNode = manager.getNode(manager.default);
|
||||
}
|
||||
if (!renderNode)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
this.renderNode = renderNode;
|
||||
this.defaultRenderNode = renderNode;
|
||||
return true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets the WebGL render node of this Game Object.
|
||||
*
|
||||
* Also sets the render node data object, if specified.
|
||||
*
|
||||
* @method Phaser.GameObjects.Components.RenderNode#setRenderNode
|
||||
* @webglOnly
|
||||
* @since 3.90.0
|
||||
* @param {string|Phaser.Renderer.WebGL.RenderNodes.RenderNode} renderNode - The render node to set on this Game Object. Either a string, or a RenderNode instance.
|
||||
* @param {object} [renderNodeData] - An object to store render node specific data in, to be read by the render nodes this Game Object uses.
|
||||
* @param {boolean} [copyData=false] - Should the data be copied from the `renderNodeData` object?
|
||||
*
|
||||
* @return {this} This Game Object instance.
|
||||
*/
|
||||
setRenderNode: function (renderNode, renderNodeData, copyData)
|
||||
{
|
||||
var renderer = this.scene.sys.renderer;
|
||||
|
||||
if (!renderer)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var manager = renderer.renderNodes;
|
||||
|
||||
if (!manager)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (typeof renderNode === 'string')
|
||||
{
|
||||
renderNode = manager.getNode(renderNode);
|
||||
}
|
||||
if (!renderNode)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
this.renderNode = renderNode;
|
||||
|
||||
if (renderNodeData)
|
||||
{
|
||||
this.renderNodeData = copyData ? DeepCopy(renderNodeData) : renderNodeData;
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Adds an entry to the `renderNodeData` object of this game object.
|
||||
*
|
||||
* If `key` is not set, it is created. If it is set, it is updated.
|
||||
*
|
||||
* If `value` is undefined and `key` exists, the key is removed.
|
||||
*
|
||||
* @method Phaser.GameObjects.Components.RenderNode#setRenderNodeData
|
||||
* @webglOnly
|
||||
* @since 3.90.0
|
||||
* @param {string} key - The key of the property to set.
|
||||
* @param {*} value - The value to set the property to.
|
||||
* @return {this} This Game Object instance.
|
||||
*/
|
||||
setRenderNodeData: function (key, value)
|
||||
{
|
||||
var data = this.renderNodeData;
|
||||
|
||||
if (value === undefined)
|
||||
{
|
||||
delete data[key];
|
||||
}
|
||||
else
|
||||
{
|
||||
data[key] = value;
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Resets the WebGL render node of this Game Object to the default.
|
||||
*
|
||||
* @method Phaser.GameObjects.Components.RenderNode#resetRenderNode
|
||||
* @webglOnly
|
||||
* @since 3.90.0
|
||||
* @param {boolean} [resetData=false] - Should the render node data be reset to an empty object?
|
||||
* @return {boolean} Whether the render node was reset successfully.
|
||||
*/
|
||||
resetRenderNode: function (resetData)
|
||||
{
|
||||
if (!resetData)
|
||||
{
|
||||
resetData = false;
|
||||
}
|
||||
|
||||
this.renderNode = this.defaultRenderNode;
|
||||
|
||||
if (resetData)
|
||||
{
|
||||
this.renderNodeData = {};
|
||||
}
|
||||
|
||||
return this.renderNode !== null;
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = RenderNode;
|
|
@ -24,6 +24,7 @@ module.exports = {
|
|||
PathFollower: require('./PathFollower'),
|
||||
Pipeline: require('./Pipeline'),
|
||||
PostPipeline: require('./PostPipeline'),
|
||||
RenderNode: require('./RenderNode'),
|
||||
ScrollFactor: require('./ScrollFactor'),
|
||||
Size: require('./Size'),
|
||||
Texture: require('./Texture'),
|
||||
|
|
|
@ -31,8 +31,8 @@ var ImageRender = require('./ImageRender');
|
|||
* @extends Phaser.GameObjects.Components.GetBounds
|
||||
* @extends Phaser.GameObjects.Components.Mask
|
||||
* @extends Phaser.GameObjects.Components.Origin
|
||||
* @extends Phaser.GameObjects.Components.Pipeline
|
||||
* @extends Phaser.GameObjects.Components.PostPipeline
|
||||
* @extends Phaser.GameObjects.Components.RenderNode
|
||||
* @extends Phaser.GameObjects.Components.ScrollFactor
|
||||
* @extends Phaser.GameObjects.Components.Size
|
||||
* @extends Phaser.GameObjects.Components.TextureCrop
|
||||
|
@ -58,8 +58,8 @@ var Image = new Class({
|
|||
Components.GetBounds,
|
||||
Components.Mask,
|
||||
Components.Origin,
|
||||
Components.Pipeline,
|
||||
Components.PostPipeline,
|
||||
Components.RenderNode,
|
||||
Components.ScrollFactor,
|
||||
Components.Size,
|
||||
Components.TextureCrop,
|
||||
|
@ -89,7 +89,7 @@ var Image = new Class({
|
|||
this.setPosition(x, y);
|
||||
this.setSizeToFrame();
|
||||
this.setOriginFromFrame();
|
||||
this.initPipeline();
|
||||
this.initRenderNode();
|
||||
this.initPostPipeline(true);
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ var ImageWebGLRenderer = function (renderer, src, drawingContext, parentMatrix)
|
|||
{
|
||||
drawingContext.camera.addToRenderList(src);
|
||||
|
||||
renderer.renderNodes.nodes.ImageQuadrangulateBatch.run(drawingContext, src, parentMatrix);
|
||||
this.renderNode.run(drawingContext, src, parentMatrix);
|
||||
};
|
||||
|
||||
module.exports = ImageWebGLRenderer;
|
||||
|
|
|
@ -35,8 +35,8 @@ var SpriteRender = require('./SpriteRender');
|
|||
* @extends Phaser.GameObjects.Components.GetBounds
|
||||
* @extends Phaser.GameObjects.Components.Mask
|
||||
* @extends Phaser.GameObjects.Components.Origin
|
||||
* @extends Phaser.GameObjects.Components.Pipeline
|
||||
* @extends Phaser.GameObjects.Components.PostPipeline
|
||||
* @extends Phaser.GameObjects.Components.RenderNode
|
||||
* @extends Phaser.GameObjects.Components.ScrollFactor
|
||||
* @extends Phaser.GameObjects.Components.Size
|
||||
* @extends Phaser.GameObjects.Components.TextureCrop
|
||||
|
@ -62,8 +62,8 @@ var Sprite = new Class({
|
|||
Components.GetBounds,
|
||||
Components.Mask,
|
||||
Components.Origin,
|
||||
Components.Pipeline,
|
||||
Components.PostPipeline,
|
||||
Components.RenderNode,
|
||||
Components.ScrollFactor,
|
||||
Components.Size,
|
||||
Components.TextureCrop,
|
||||
|
@ -106,7 +106,7 @@ var Sprite = new Class({
|
|||
this.setPosition(x, y);
|
||||
this.setSizeToFrame();
|
||||
this.setOriginFromFrame();
|
||||
this.initPipeline();
|
||||
this.initRenderNode();
|
||||
this.initPostPipeline(true);
|
||||
},
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ var SpriteWebGLRenderer = function (renderer, src, drawingContext, parentMatrix)
|
|||
{
|
||||
drawingContext.camera.addToRenderList(src);
|
||||
|
||||
renderer.renderNodes.nodes.ImageQuadrangulateBatch.run(drawingContext, src, parentMatrix);
|
||||
this.renderNode.run(drawingContext, src, parentMatrix);
|
||||
};
|
||||
|
||||
module.exports = SpriteWebGLRenderer;
|
||||
|
|
|
@ -68,8 +68,8 @@ var UUID = require('../../utils/string/UUID');
|
|||
* @extends Phaser.GameObjects.Components.GetBounds
|
||||
* @extends Phaser.GameObjects.Components.Mask
|
||||
* @extends Phaser.GameObjects.Components.Origin
|
||||
* @extends Phaser.GameObjects.Components.Pipeline
|
||||
* @extends Phaser.GameObjects.Components.PostPipeline
|
||||
* @extends Phaser.GameObjects.Components.RenderNode
|
||||
* @extends Phaser.GameObjects.Components.ScrollFactor
|
||||
* @extends Phaser.GameObjects.Components.Tint
|
||||
* @extends Phaser.GameObjects.Components.Transform
|
||||
|
@ -97,8 +97,8 @@ var Text = new Class({
|
|||
Components.GetBounds,
|
||||
Components.Mask,
|
||||
Components.Origin,
|
||||
Components.Pipeline,
|
||||
Components.PostPipeline,
|
||||
Components.RenderNode,
|
||||
Components.ScrollFactor,
|
||||
Components.Tint,
|
||||
Components.Transform,
|
||||
|
@ -126,7 +126,7 @@ var Text = new Class({
|
|||
|
||||
this.setPosition(x, y);
|
||||
this.setOrigin(0, 0);
|
||||
this.initPipeline();
|
||||
this.initRenderNode();
|
||||
this.initPostPipeline(true);
|
||||
|
||||
/**
|
||||
|
|
|
@ -27,7 +27,7 @@ var TextWebGLRenderer = function (renderer, src, drawingContext, parentMatrix)
|
|||
|
||||
drawingContext.camera.addToRenderList(src);
|
||||
|
||||
renderer.renderNodes.nodes.ImageQuadrangulateBatch.run(drawingContext, src, parentMatrix);
|
||||
this.renderNode.run(drawingContext, src, parentMatrix);
|
||||
};
|
||||
|
||||
module.exports = TextWebGLRenderer;
|
||||
|
|
|
@ -103,8 +103,8 @@ var VideoRender = require('./VideoRender');
|
|||
* @extends Phaser.GameObjects.Components.GetBounds
|
||||
* @extends Phaser.GameObjects.Components.Mask
|
||||
* @extends Phaser.GameObjects.Components.Origin
|
||||
* @extends Phaser.GameObjects.Components.Pipeline
|
||||
* @extends Phaser.GameObjects.Components.PostPipeline
|
||||
* @extends Phaser.GameObjects.Components.RenderNode
|
||||
* @extends Phaser.GameObjects.Components.ScrollFactor
|
||||
* @extends Phaser.GameObjects.Components.TextureCrop
|
||||
* @extends Phaser.GameObjects.Components.Tint
|
||||
|
@ -129,8 +129,8 @@ var Video = new Class({
|
|||
Components.GetBounds,
|
||||
Components.Mask,
|
||||
Components.Origin,
|
||||
Components.Pipeline,
|
||||
Components.PostPipeline,
|
||||
Components.RenderNode,
|
||||
Components.ScrollFactor,
|
||||
Components.TextureCrop,
|
||||
Components.Tint,
|
||||
|
@ -195,7 +195,7 @@ var Video = new Class({
|
|||
* If you have saved this video to a texture via the `saveTexture` method, this controls if the video
|
||||
* is rendered with `flipY` in WebGL or not. You often need to set this if you wish to use the video texture
|
||||
* as the input source for a shader. If you find your video is appearing upside down within a shader or
|
||||
* custom pipeline, flip this property.
|
||||
* custom renderer, flip this property.
|
||||
*
|
||||
* @name Phaser.GameObjects.Video#flipY
|
||||
* @type {boolean}
|
||||
|
@ -517,7 +517,7 @@ var Video = new Class({
|
|||
|
||||
this.setPosition(x, y);
|
||||
this.setSize(256, 256);
|
||||
this.initPipeline();
|
||||
this.initRenderNode();
|
||||
this.initPostPipeline(true);
|
||||
|
||||
game.events.on(GameEvents.PAUSE, this.globalPause, this);
|
||||
|
|
|
@ -27,7 +27,7 @@ var VideoWebGLRenderer = function (renderer, src, drawingContext, parentMatrix)
|
|||
|
||||
drawingContext.camera.addToRenderList(src);
|
||||
|
||||
renderer.renderNodes.nodes.ImageQuadrangulateBatch.run(drawingContext, src, parentMatrix);
|
||||
this.renderNode.run(drawingContext, src, parentMatrix);
|
||||
};
|
||||
|
||||
module.exports = VideoWebGLRenderer;
|
||||
|
|
|
@ -158,6 +158,17 @@ var WebGLRenderer = new Class({
|
|||
*/
|
||||
this.renderNodes = null;
|
||||
|
||||
/**
|
||||
* The RenderNode to use for rendering individual cameras.
|
||||
*
|
||||
* This will be populated during the `boot` method.
|
||||
*
|
||||
* @name Phaser.Renderer.WebGL.WebGLRenderer#cameraRenderNode
|
||||
* @type {Phaser.Renderer.WebGL.RenderNodes.RenderNode}
|
||||
* @since 3.90.0
|
||||
*/
|
||||
this.cameraRenderNode = null;
|
||||
|
||||
/**
|
||||
* The width of the canvas being rendered to.
|
||||
* This is populated in the onResize event handler.
|
||||
|
@ -1068,9 +1079,11 @@ var WebGLRenderer = new Class({
|
|||
//
|
||||
// pipelineManager.boot(config.pipeline, config.defaultPipeline, config.autoMobilePipeline);
|
||||
|
||||
// Set up render steps.
|
||||
// Set up render nodes.
|
||||
this.renderNodes = new RenderNodeManager(this);
|
||||
|
||||
this.cameraRenderNode = this.renderNodes.getNode('Camera');
|
||||
|
||||
// Set-up default textures, fbo and scissor
|
||||
|
||||
this.blankTexture = game.textures.getFrame('__DEFAULT').glTexture;
|
||||
|
@ -2800,7 +2813,7 @@ var WebGLRenderer = new Class({
|
|||
|
||||
this.emit(Events.RENDER, scene, camera);
|
||||
|
||||
this.renderNodes.nodes.Camera.run(this.baseDrawingContext, children, camera);
|
||||
this.cameraRenderNode.run(this.baseDrawingContext, children, camera);
|
||||
|
||||
return;
|
||||
// OLD CODE:
|
||||
|
|
|
@ -16,6 +16,7 @@ var WebGL = {
|
|||
DrawingContext: require('./DrawingContext'),
|
||||
PipelineManager: require('./PipelineManager'),
|
||||
Pipelines: require('./pipelines'),
|
||||
RenderNodes: require('./renderNodes'),
|
||||
RenderTarget: require('./RenderTarget'),
|
||||
Utils: require('./Utils'),
|
||||
WebGLPipeline: require('./WebGLPipeline'),
|
||||
|
|
|
@ -1,68 +0,0 @@
|
|||
/**
|
||||
* @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 RenderNode = require('./RenderNode');
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* A Batch Render Node.
|
||||
*
|
||||
* This is a base class used for other Batch Render Nodes.
|
||||
*
|
||||
* A batch is a collection of objects that can be drawn in a single call.
|
||||
* They must use the same vertex buffer format and the same shader.
|
||||
* This is very efficient for rendering many objects at once.
|
||||
*
|
||||
* Instead of being rendered immediately, batch primitives are accumulated
|
||||
* until the batch is drawn, known as a 'flush'. A flush is triggered
|
||||
* automatically in the following cases:
|
||||
*
|
||||
* - The batch is full. What this means is defined by the batch itself.
|
||||
* It is usually the size of the vertex buffer,
|
||||
* or the number of texture units.
|
||||
* - A DrawingContext is used or released. This might change the
|
||||
* drawing area, the blend mode, or the target framebuffer.
|
||||
* It also occurs at the end of the frame.
|
||||
* - A different thing must be drawn. This is either a Stand-Alone Render,
|
||||
* or a different Batch RenderNode.
|
||||
*
|
||||
* Thus, the RenderNodeManager must track which Batch is currently being
|
||||
* used, so that it can be flushed when necessary.
|
||||
*
|
||||
* @class Batch
|
||||
* @memberof Phaser.Renderer.WebGL.RenderNodes
|
||||
* @extends Phaser.Renderer.WebGL.RenderNodes.RenderNode
|
||||
* @constructor
|
||||
* @since 3.90.0
|
||||
*
|
||||
* @param {Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager} manager - The manager that owns this RenderNode.
|
||||
* @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - The renderer that owns this RenderNode.
|
||||
*/
|
||||
var Batch = new Class({
|
||||
Extends: RenderNode,
|
||||
|
||||
initialize: function Batch (name, manager, renderer)
|
||||
{
|
||||
RenderNode.call(this, name, manager, renderer);
|
||||
},
|
||||
|
||||
/**
|
||||
* Receive data to add to the current batch.
|
||||
*
|
||||
* This method should be extended to handle the data specific to a subclass.
|
||||
* In particular, it should notify the RenderNodeManager, e.g. via
|
||||
* `this.manager.setCurrentBatchNode(this, currentContext, camera);`,
|
||||
* which will trigger a flush and switch if necessary.
|
||||
*
|
||||
* @method Phaser.Renderer.WebGL.RenderNodes.Batch#batch
|
||||
* @since 3.90.0
|
||||
*/
|
||||
batch: function ()
|
||||
{}
|
||||
});
|
||||
|
||||
module.exports = Batch;
|
388
src/renderer/webgl/renderNodes/BatchHandler.js
Normal file
388
src/renderer/webgl/renderNodes/BatchHandler.js
Normal file
|
@ -0,0 +1,388 @@
|
|||
/**
|
||||
* @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');
|
||||
var WebGLVertexBufferLayoutWrapper = require('../wrappers/WebGLVertexBufferLayoutWrapper');
|
||||
var RenderNode = require('./RenderNode');
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* A Batch Handler Render Node. This is a base class used for other
|
||||
* Batch Handler Render Nodes.
|
||||
*
|
||||
* A batch handler buffers data for a batch of objects to be rendered
|
||||
* together. It is responsible for the vertex buffer layout and shaders
|
||||
* used to render the batched items.
|
||||
*
|
||||
* This class is not meant to be used directly, but to be extended by
|
||||
* other classes.
|
||||
*
|
||||
* @class BatchHandler
|
||||
* @memberof Phaser.Renderer.WebGL.RenderNodes
|
||||
* @constructor
|
||||
* @since 3.90.0
|
||||
* @extends Phaser.Renderer.WebGL.RenderNodes.RenderNode
|
||||
* @param {Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager} manager - The manager that owns this RenderNode.
|
||||
* @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - The renderer that owns this RenderNode.
|
||||
* @param {Phaser.Renderer.WebGL.RenderNodes.BatchHandlerConfig} [config] - The configuration object for this RenderNode.
|
||||
* @param {Phaser.Renderer.WebGL.RenderNodes.BatchHandlerConfig} defaultConfig - The default configuration object for this RenderNode. This is used to ensure all required properties are present, so it must be complete.
|
||||
*/
|
||||
var BatchHandler = new Class({
|
||||
Extends: RenderNode,
|
||||
|
||||
initialize: function BatchHandler (manager, renderer, config, defaultConfig)
|
||||
{
|
||||
var gl = renderer.gl;
|
||||
|
||||
config = this._copyAndCompleteConfig(config || {}, defaultConfig);
|
||||
|
||||
var name = config.name;
|
||||
if (!name)
|
||||
{
|
||||
throw new Error('BatchHandler must have a name');
|
||||
}
|
||||
|
||||
RenderNode.call(this, name, manager, renderer);
|
||||
|
||||
/**
|
||||
* The number of instances per batch, used to determine the size of the
|
||||
* vertex buffer, and the number of instances to render.
|
||||
*
|
||||
* This is usually limited by the maximum number of vertices that can be
|
||||
* distinguished with a 16-bit UNSIGNED_INT index buffer,
|
||||
* which is 65536. This is set in the game render config as `batchSize`.
|
||||
*
|
||||
* @name Phaser.Renderer.WebGL.RenderNodes.BatchHandler#instancesPerBatch
|
||||
* @type {number}
|
||||
* @since 3.90.0
|
||||
*/
|
||||
this.instancesPerBatch = -1;
|
||||
|
||||
/**
|
||||
* The number of vertices per instance.
|
||||
*
|
||||
* This is usually 4 for a quad.
|
||||
*
|
||||
* Each vertex corresponds to an index in the element buffer.
|
||||
*
|
||||
* @name Phaser.Renderer.WebGL.RenderNodes.BatchHandler#verticesPerInstance
|
||||
* @type {number}
|
||||
* @since 3.90.0
|
||||
* @default 4
|
||||
*/
|
||||
this.verticesPerInstance = config.verticesPerInstance;
|
||||
|
||||
// Calculate the final number of instances per batch.
|
||||
var indexLimit = 65536; // 2^16
|
||||
var maxInstances = Math.floor(indexLimit / this.verticesPerInstance);
|
||||
var targetInstances = config.instancesPerBatch || this.renderer.config.batchSize || maxInstances;
|
||||
this.instancesPerBatch = Math.min(targetInstances, maxInstances);
|
||||
|
||||
/**
|
||||
* The number of indices per instance.
|
||||
* This is usually 6 for a quad.
|
||||
* Each index corresponds to a vertex in the vertex buffer.
|
||||
*
|
||||
* @name Phaser.Renderer.WebGL.RenderNodes.BatchHandler#indicesPerInstance
|
||||
* @type {number}
|
||||
* @since 3.90.0
|
||||
* @default 6
|
||||
*/
|
||||
this.indicesPerInstance = config.indicesPerInstance;
|
||||
|
||||
/**
|
||||
* The number of bytes per index per instance.
|
||||
* This is used to advance the index buffer, and accounts for the
|
||||
* size of a Uint16Array element.
|
||||
*
|
||||
* @name Phaser.Renderer.WebGL.RenderNodes.BatchHandler#bytesPerIndexPerInstance
|
||||
* @type {number}
|
||||
* @since 3.90.0
|
||||
* @default 12
|
||||
*/
|
||||
this.bytesPerIndexPerInstance = this.indicesPerInstance * Uint16Array.BYTES_PER_ELEMENT;
|
||||
|
||||
/**
|
||||
* The maximum number of textures per batch entry.
|
||||
* This is usually the maximum number of texture units available,
|
||||
* but it might be smaller for some uses.
|
||||
*
|
||||
* @name Phaser.Renderer.WebGL.RenderNodes.BatchHandler#maxTexturesPerBatch
|
||||
* @type {number}
|
||||
* @since 3.90.0
|
||||
*/
|
||||
this.maxTexturesPerBatch = manager.maxParallelTextureUnits;
|
||||
|
||||
// Listen for changes to the number of draw calls per batch.
|
||||
this.manager.on(
|
||||
Phaser.Renderer.Events.SET_PARALLEL_TEXTURE_UNITS,
|
||||
this.updateTextureCount,
|
||||
this
|
||||
);
|
||||
|
||||
/**
|
||||
* The raw fragment shader source code.
|
||||
*
|
||||
* This is used to generate the final fragment shader source code,
|
||||
* which is then compiled into a shader program.
|
||||
* The final source code may apply some templates to the raw source
|
||||
* via `Utils.parseFragmentShaderMaxTextures`,
|
||||
* generally to set the number of textures per batch,
|
||||
* which may change at runtime.
|
||||
*
|
||||
* @name Phaser.Renderer.WebGL.RenderNodes.BatchHandler#rawShaderSourceFS
|
||||
* @type {string}
|
||||
* @since 3.90.0
|
||||
*/
|
||||
this.rawShaderSourceFS = config.fragmentSource;
|
||||
|
||||
/**
|
||||
* The WebGL program used to render the Game Object.
|
||||
*
|
||||
* @name Phaser.Renderer.WebGL.RenderNodes.Single#program
|
||||
* @type {Phaser.Renderer.WebGL.Wrappers.WebGLProgramWrapper}
|
||||
* @since 3.90.0
|
||||
*/
|
||||
this.program = renderer.createProgram(
|
||||
config.vertexSource,
|
||||
Utils.parseFragmentShaderMaxTextures(
|
||||
this.rawShaderSourceFS,
|
||||
this.maxTexturesPerBatch
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* The index buffer defining vertex order.
|
||||
*
|
||||
* @name Phaser.Renderer.WebGL.RenderNodes.BatchHandler#indexBuffer
|
||||
* @type {Phaser.Renderer.WebGL.Wrappers.WebGLBufferWrapper}
|
||||
* @since 3.90.0
|
||||
*/
|
||||
this.indexBuffer = renderer.createIndexBuffer(
|
||||
this._generateElementIndices(this.instancesPerBatch),
|
||||
gl.STATIC_DRAW
|
||||
);
|
||||
|
||||
// Prepare the vertex buffer layout.
|
||||
var partialLayout = config.vertexBufferLayout;
|
||||
partialLayout.count = this.instancesPerBatch * this.verticesPerInstance;
|
||||
|
||||
/**
|
||||
* The layout, data, and vertex buffer used to store the vertex data.
|
||||
*
|
||||
* The default layout is for a quad with position, texture coordinate,
|
||||
* texture ID, tint effect, and tint color on each vertex.
|
||||
*
|
||||
* @name Phaser.Renderer.WebGL.RenderNodes.BatchHandler#vertexBufferLayout
|
||||
* @type {Phaser.Renderer.WebGL.Wrappers.WebGLVertexBufferLayoutWrapper}
|
||||
* @since 3.90.0
|
||||
*/
|
||||
this.vertexBufferLayout = new WebGLVertexBufferLayoutWrapper(
|
||||
renderer,
|
||||
this.program,
|
||||
partialLayout
|
||||
);
|
||||
|
||||
/**
|
||||
* The Vertex Array Object used to render the batch.
|
||||
*
|
||||
* @name Phaser.Renderer.WebGL.RenderNodes.Single#vao
|
||||
* @type {Phaser.Renderer.WebGL.Wrappers.WebGLVAOWrapper}
|
||||
* @since 3.90.0
|
||||
*/
|
||||
this.vao = renderer.createVAO(this.indexBuffer, [
|
||||
this.vertexBufferLayout
|
||||
]);
|
||||
|
||||
/**
|
||||
* The number of floats per instance, used to determine how much of the vertex buffer to update.
|
||||
*
|
||||
* @name Phaser.Renderer.WebGL.RenderNodes.BatchHandler#floatsPerInstance
|
||||
* @type {number}
|
||||
* @since 3.90.0
|
||||
*/
|
||||
this.floatsPerInstance = this.vertexBufferLayout.layout.stride * this.verticesPerInstance / Float32Array.BYTES_PER_ELEMENT;
|
||||
|
||||
/**
|
||||
* The current batch entry being filled with textures.
|
||||
*
|
||||
* @name Phaser.Renderer.WebGL.RenderNodes.BatchHandler#currentBatchEntry
|
||||
* @type {Phaser.Types.Renderer.WebGL.WebGLPipelineBatchEntry}
|
||||
* @since 3.90.0
|
||||
*/
|
||||
this.currentBatchEntry = {
|
||||
start: 0,
|
||||
count: 0,
|
||||
unit: 0,
|
||||
texture: []
|
||||
};
|
||||
|
||||
/**
|
||||
* The entries in the batch.
|
||||
* Each entry represents a "sub-batch" of quads which use the same
|
||||
* pool of textures. This allows the renderer to continue to buffer
|
||||
* quads into the same batch without needing to upload the vertex
|
||||
* buffer. When the batch flushes, there will be one vertex buffer
|
||||
* upload, and one draw call per batch entry.
|
||||
*
|
||||
* @name Phaser.Renderer.WebGL.RenderNodes.BatchHandler#batchEntries
|
||||
* @type {Phaser.Types.Renderer.WebGL.WebGLPipelineBatchEntry[]}
|
||||
* @since 3.90.0
|
||||
* @default []
|
||||
*/
|
||||
this.batchEntries = [];
|
||||
|
||||
/**
|
||||
* The number of instances currently in the batch.
|
||||
*
|
||||
* @name Phaser.Renderer.WebGL.RenderNodes.BatchHandler#instanceCount
|
||||
* @type {number}
|
||||
* @since 3.90.0
|
||||
*/
|
||||
this.instanceCount = 0;
|
||||
|
||||
// Set the dimension-related uniforms and listen for resize events.
|
||||
this.resize(renderer.width, renderer.height);
|
||||
this.renderer.on(Phaser.Renderer.Events.RESIZE, this.resize, this);
|
||||
},
|
||||
|
||||
/**
|
||||
* Copy and complete the configuration object.
|
||||
* This prevents the original config object from being modified.
|
||||
*
|
||||
* Default values are used for any missing properties.
|
||||
* These defaults are based on the default quad shader and layout.
|
||||
*
|
||||
* @method Phaser.Renderer.WebGL.RenderNodes.BatchHandler#_copyAndCompleteConfig
|
||||
* @since 3.90.0
|
||||
* @private
|
||||
* @param {Phaser.Renderer.WebGL.RenderNodes.BatchHandlerConfig} config - The configuration object.
|
||||
* @param {Phaser.Renderer.WebGL.RenderNodes.BatchHandlerConfig} defaultConfig - The default configuration object.
|
||||
*/
|
||||
_copyAndCompleteConfig: function (config, defaultConfig)
|
||||
{
|
||||
var newConfig = {};
|
||||
|
||||
newConfig.name = config.name || defaultConfig.name;
|
||||
newConfig.verticesPerInstance = config.verticesPerInstance || defaultConfig.verticesPerInstance;
|
||||
newConfig.indicesPerInstance = config.indicesPerInstance || defaultConfig.indicesPerInstance;
|
||||
newConfig.vertexSource = config.vertexSource || defaultConfig.vertexSource;
|
||||
newConfig.fragmentSource = config.fragmentSource || defaultConfig.fragmentSource;
|
||||
|
||||
// These may be left undefined to auto-calculate instance count.
|
||||
newConfig.instancesPerBatch = config.instancesPerBatch;
|
||||
newConfig.maxTexturesPerBatch = config.maxTexturesPerBatch;
|
||||
|
||||
// Set up vertex buffer layout.
|
||||
var layoutSource = config.vertexBufferLayout || defaultConfig.vertexBufferLayout;
|
||||
newConfig.vertexBufferLayout = {};
|
||||
newConfig.vertexBufferLayout.usage = layoutSource.usage;
|
||||
newConfig.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;
|
||||
}
|
||||
newConfig.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];
|
||||
newConfig.vertexBufferLayout.layout.push({
|
||||
name: addAttr.name,
|
||||
size: addAttr.size || 1,
|
||||
type: addAttr.type || 'FLOAT',
|
||||
normalized: addAttr.normalized || false
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return newConfig;
|
||||
},
|
||||
|
||||
/**
|
||||
* Generate element indices for the instance vertices.
|
||||
* This should be overridden by subclasses.
|
||||
* This is called automatically when the node is initialized.
|
||||
*
|
||||
* @method Phaser.Renderer.WebGL.RenderNodes.BatchHandler#_generateElementIndices
|
||||
* @since 3.90.0
|
||||
* @private
|
||||
* @param {number} instances - The number of instances to define.
|
||||
* @return {Uint16Array} The index buffer data.
|
||||
*/
|
||||
_generateElementIndices: function (instances)
|
||||
{
|
||||
// This is meaningless and should be overridden by subclasses.
|
||||
return new Uint16Array(instances);
|
||||
},
|
||||
|
||||
/**
|
||||
* Set new dimensions for the renderer.
|
||||
* This should be overridden by subclasses.
|
||||
*
|
||||
* This is called automatically when the renderer is resized.
|
||||
*
|
||||
* @method Phaser.Renderer.WebGL.RenderNodes.BatchTexturedTintedTransformedQuads#resize
|
||||
* @since 3.90.0
|
||||
* @param {number} width - The new width of the renderer.
|
||||
* @param {number} height - The new height of the renderer.
|
||||
*/
|
||||
resize: function (width, height) {},
|
||||
|
||||
/**
|
||||
* Update the number of draw calls per batch.
|
||||
* This should be overridden by subclasses.
|
||||
*
|
||||
* This is called automatically by a listener
|
||||
* for the `Phaser.Renderer.Events.SET_PARALLEL_TEXTURE_UNITS` event,
|
||||
* triggered by the RenderNodeManager.
|
||||
*
|
||||
* @method Phaser.Renderer.WebGL.RenderNodes.Pressurizer#updateTextureCount
|
||||
* @since 3.90.0
|
||||
* @param {number} [count] - The new number of draw calls per batch. If undefined, the maximum number of texture units is used.
|
||||
*/
|
||||
updateTextureCount: function (count) {},
|
||||
|
||||
/**
|
||||
* Draw then empty the current batch.
|
||||
*
|
||||
* This method is called automatically, by either this node or the manager,
|
||||
* when the batch is full, or when something else needs to be rendered.
|
||||
*
|
||||
* This method should be overridden by subclasses.
|
||||
*
|
||||
* @method Phaser.Renderer.WebGL.RenderNodes.BatchHandler#run
|
||||
* @since 3.90.0
|
||||
* @param {Phaser.Types.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context.
|
||||
*/
|
||||
run: function (drawingContext) {},
|
||||
|
||||
/**
|
||||
* Add an instance to the batch. Game objects call this method to add
|
||||
* themselves to the batch. This method should be overridden by subclasses.
|
||||
*
|
||||
* @method Phaser.Renderer.WebGL.RenderNodes.BatchHandler#batch
|
||||
* @since 3.90.0
|
||||
*/
|
||||
batch: function () {}
|
||||
});
|
||||
|
||||
module.exports = BatchHandler;
|
|
@ -24,6 +24,26 @@ var Camera = new Class({
|
|||
initialize: function Camera (manager, renderer)
|
||||
{
|
||||
RenderNode.call(this, 'Camera', manager, renderer);
|
||||
|
||||
/**
|
||||
* The RenderNode that handles filling the camera with a
|
||||
* flat color. This is used to render the camera background,
|
||||
* flash effects, and fade effects.
|
||||
*
|
||||
* @name Phaser.Renderer.WebGL.RenderNodes.Camera#fillCameraNode
|
||||
* @type {Phaser.Renderer.WebGL.RenderNodes.FillCamera}
|
||||
* @since 3.90.0
|
||||
*/
|
||||
this.fillCameraNode = manager.getNode('FillCamera');
|
||||
|
||||
/**
|
||||
* The RenderNode that handles rendering lists of children.
|
||||
*
|
||||
* @name Phaser.Renderer.WebGL.RenderNodes.Camera#listCompositorNode
|
||||
* @type {Phaser.Renderer.WebGL.RenderNodes.ListCompositor}
|
||||
* @since 3.90.0
|
||||
*/
|
||||
this.listCompositorNode = manager.getNode('ListCompositor');
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -56,18 +76,18 @@ var Camera = new Class({
|
|||
// Enter drawing context.
|
||||
currentContext.use();
|
||||
|
||||
var FillCamera = this.manager.nodes.FillCamera;
|
||||
var fillCamera = this.fillCameraNode;
|
||||
|
||||
// Draw camera background.
|
||||
if (camera.backgroundColor.alphaGL > 0)
|
||||
{
|
||||
var bg = camera.backgroundColor;
|
||||
var col = GetColor32(bg.red, bg.green, bg.blue, bg.alpha);
|
||||
FillCamera.run(currentContext, col);
|
||||
fillCamera.run(currentContext, col);
|
||||
}
|
||||
|
||||
// Draw children.
|
||||
this.manager.nodes.ListCompositor.run(currentContext, children, parentTransformMatrix);
|
||||
this.listCompositorNode.run(currentContext, children, parentTransformMatrix);
|
||||
|
||||
// Draw camera post effects.
|
||||
|
||||
|
@ -75,14 +95,14 @@ var Camera = new Class({
|
|||
if (flashEffect.postRenderWebGL())
|
||||
{
|
||||
col = GetColor32(flashEffect.red, flashEffect.green, flashEffect.blue, flashEffect.alpha * 255);
|
||||
FillCamera.run(currentContext, col);
|
||||
fillCamera.run(currentContext, col);
|
||||
}
|
||||
|
||||
var fadeEffect = camera.fadeEffect;
|
||||
if (fadeEffect.postRenderWebGL())
|
||||
{
|
||||
col = GetColor32(fadeEffect.red, fadeEffect.green, fadeEffect.blue, fadeEffect.alpha * 255);
|
||||
FillCamera.run(currentContext, col);
|
||||
fillCamera.run(currentContext, col);
|
||||
}
|
||||
|
||||
// Finish rendering.
|
||||
|
|
|
@ -25,6 +25,15 @@ var FillCamera = new Class({
|
|||
initialize: function FillCamera (manager, renderer)
|
||||
{
|
||||
RenderNode.call(this, 'FillCamera', manager, renderer);
|
||||
|
||||
/**
|
||||
* The RenderNode that draws a filled rectangle.
|
||||
*
|
||||
* @name Phaser.Renderer.WebGL.RenderNodes.FillCamera#fillRectNode
|
||||
* @type {Phaser.Renderer.WebGL.RenderNodes.FillRect}
|
||||
* @since 3.90.0
|
||||
*/
|
||||
this.fillRectNode = this.manager.getNode('FillRect');
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -44,7 +53,7 @@ var FillCamera = new Class({
|
|||
var cw = camera.width;
|
||||
var ch = camera.height;
|
||||
|
||||
this.manager.nodes.FillRect.run(drawingContext, null, cx, cy, cw, ch, color, color, color, color, 2);
|
||||
this.fillRectNode.run(drawingContext, null, cx, cy, cw, ch, color, color, color, color, 2);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -31,6 +31,15 @@ var FillRect = new Class({
|
|||
{
|
||||
RenderNode.call(this, 'FillRect', manager, renderer);
|
||||
|
||||
/**
|
||||
* The QuadBatchHandler that handles the rendering of quads.
|
||||
*
|
||||
* @name Phaser.Renderer.WebGL.RenderNodes.FillRect#quadBatchHandlerNode
|
||||
* @type {Phaser.Renderer.WebGL.RenderNodes.QuadBatchHandler}
|
||||
* @since 3.90.0
|
||||
*/
|
||||
this.quadBatchHandlerNode = this.manager.getNode('QuadBatchHandler');
|
||||
|
||||
/**
|
||||
* An unchanging identity matrix.
|
||||
*
|
||||
|
@ -84,7 +93,7 @@ var FillRect = new Class({
|
|||
|
||||
var quad = currentMatrix.setQuad(x, y, x + width, y + height);
|
||||
|
||||
this.manager.nodes.BatchTexturedTintedTransformedQuads.batch(
|
||||
this.quadBatchHandlerNode.batch(
|
||||
drawingContext,
|
||||
this.renderer.whiteTexture,
|
||||
|
||||
|
|
|
@ -16,20 +16,67 @@ var getTint = Utils.getTintAppendFloatAlpha;
|
|||
* A RenderNode which computes a StandardBatchRenderQuad (SBR-Quad) from an
|
||||
* Image-like GameObject.
|
||||
*
|
||||
* @class ImageQuadrangulateBatch
|
||||
* This node computes the vertices and texture properties of a single quad.
|
||||
* The quad is then batched with other quads to be rendered together at some
|
||||
* later point in the render sequence.
|
||||
* This is useful for rendering many similar objects at once.
|
||||
*
|
||||
* This RenderNode is configurable. Most of the time, this involves setting
|
||||
* the `config.batchHandler` property to a custom batch handler configuration.
|
||||
* The batch handler contains the vertex buffer layout and shaders used to
|
||||
* render the batched items.
|
||||
*
|
||||
* The default batch handler is `QuadBatchHandler`. It is set up to handle
|
||||
* Standard Batch Render Quads (SBR-Quads) as the parameters of its `batch`
|
||||
* method. These define a quad with a texture reference, texture
|
||||
* coordinates as a box, vertex coordinates for each corner,
|
||||
* tint colors for each corner, and a tint fill value. SBR-Quads are
|
||||
* the default, efficient way to render images and sprites.
|
||||
*
|
||||
* If you want to render something that doesn't fit the SBR-Quad format,
|
||||
* you will need to customize more than just the batch handler.
|
||||
* Configure a new `run` method to invoke your custom batch handler
|
||||
* with the correct parameters.
|
||||
*
|
||||
* @class GameObjectBatcher
|
||||
* @memberof Phaser.Renderer.WebGL.RenderNodes
|
||||
* @constructor
|
||||
* @since 3.90.0
|
||||
* @extends Phaser.Renderer.WebGL.RenderNodes.RenderNode
|
||||
* @param {Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager} manager - The manager that owns this RenderNode.
|
||||
* @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - The renderer that owns this RenderNode.
|
||||
* @param {Phaser.Renderer.WebGL.RenderNodes.GameObjectBatcherConfig} [config] - The configuration object for this RenderNode.
|
||||
*/
|
||||
var ImageQuadrangulateBatch = new Class({
|
||||
var GameObjectBatcher = new Class({
|
||||
Extends: RenderNode,
|
||||
|
||||
initialize: function ImageQuadrangulateBatch (manager, renderer)
|
||||
initialize: function GameObjectBatcher (manager, renderer, config)
|
||||
{
|
||||
RenderNode.call(this, 'ImageQuadrangulateBatch', manager, renderer);
|
||||
if (config === undefined) { config = {}; }
|
||||
|
||||
var name = config.name || 'GameObjectBatcher';
|
||||
|
||||
RenderNode.call(this, name, manager, renderer);
|
||||
|
||||
var batchHandler = 'QuadBatchHandler';
|
||||
if (config.batchHandler)
|
||||
{
|
||||
var batchHandlerIsConfig = typeof config.batchHandler === 'object';
|
||||
batchHandler = batchHandlerIsConfig ? config.batchHandler.name : config.batchHandler;
|
||||
if (batchHandlerIsConfig && !manager.hasNode(batchHandler))
|
||||
{
|
||||
manager.addNodeConstructor(batchHandler, config.batchHandler);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The batch handler used to render the quads.
|
||||
*
|
||||
* @name Phaser.Renderer.WebGL.RenderNodes.GameObjectBatcher#batchHandler
|
||||
* @type {Phaser.Renderer.WebGL.RenderNodes.BatchHandler}
|
||||
* @since 3.90.0
|
||||
*/
|
||||
this.batchHandler = manager.getNode(batchHandler);
|
||||
|
||||
/**
|
||||
* The matrix used internally to compute camera transforms.
|
||||
|
@ -65,7 +112,7 @@ var ImageQuadrangulateBatch = new Class({
|
|||
/**
|
||||
* Render the GameObject.
|
||||
*
|
||||
* @method Phaser.Renderer.WebGL.RenderNodes.ImageQuadrangulateBatch#run
|
||||
* @method Phaser.Renderer.WebGL.RenderNodes.GameObjectBatcher#run
|
||||
* @since 3.90.0
|
||||
* @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The context currently in use.
|
||||
* @param {Phaser.GameObjects.Image} gameObject - The GameObject being rendered.
|
||||
|
@ -174,7 +221,7 @@ var ImageQuadrangulateBatch = new Class({
|
|||
|
||||
var quad = calcMatrix.setQuad(x, y, x + frameWidth, y + frameHeight);
|
||||
|
||||
this.manager.nodes.BatchTexturedTintedTransformedQuads.batch(
|
||||
this.batchHandler.batch(
|
||||
drawingContext,
|
||||
|
||||
// Use `frame.source.glTexture` instead of `frame.glTexture`
|
||||
|
@ -200,4 +247,4 @@ var ImageQuadrangulateBatch = new Class({
|
|||
}
|
||||
});
|
||||
|
||||
module.exports = ImageQuadrangulateBatch;
|
||||
module.exports = GameObjectBatcher;
|
|
@ -1,190 +0,0 @@
|
|||
/**
|
||||
* @author Benjamin D. Richards <benjamindrichards@gmail.com>
|
||||
* @copyright 2013-2024 Phaser Studio Inc.
|
||||
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
||||
*/
|
||||
|
||||
var TransformMatrix = require('../../../gameobjects/components/TransformMatrix.js');
|
||||
var Class = require('../../../utils/Class');
|
||||
var RenderNode = require('./RenderNode');
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* A RenderNode which computes a 2D matrix transform for a quad.
|
||||
* This matrix will transform a base quad covering ((0,0), (1,1))
|
||||
* to cover the game object's screen region.
|
||||
*
|
||||
* @class GetQuadTransform
|
||||
* @memberof Phaser.Renderer.WebGL.RenderNodes
|
||||
* @constructor
|
||||
* @since 3.90.0
|
||||
* @extends Phaser.Renderer.WebGL.RenderNodes.RenderNode
|
||||
* @param {Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager} manager - The manager that owns this RenderNode.
|
||||
* @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - The renderer that owns this RenderNode.
|
||||
*/
|
||||
var GetQuadTransform = new Class({
|
||||
Extends: RenderNode,
|
||||
|
||||
initialize: function GetQuadTransform (manager, renderer)
|
||||
{
|
||||
RenderNode.call(this, 'GetQuadTransform', manager, renderer);
|
||||
|
||||
/**
|
||||
* The matrix used internally to compute camera transforms.
|
||||
*
|
||||
* @name Phaser.Renderer.WebGL.RenderNodes.Single#_camMatrix
|
||||
* @type {Phaser.GameObjects.Components.TransformMatrix}
|
||||
* @since 3.90.0
|
||||
* @private
|
||||
*/
|
||||
this._camMatrix = new TransformMatrix();
|
||||
|
||||
/**
|
||||
* The matrix used internally to compute sprite transforms.
|
||||
*
|
||||
* @name Phaser.Renderer.WebGL.RenderNodes.Single#_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.Single#_calcMatrix
|
||||
* @type {Phaser.GameObjects.Components.TransformMatrix}
|
||||
* @since 3.90.0
|
||||
* @private
|
||||
*/
|
||||
this._calcMatrix = new TransformMatrix();
|
||||
},
|
||||
|
||||
/**
|
||||
* Compute a 2D matrix transform for a quad.
|
||||
*
|
||||
* The return value is an object held by this node,
|
||||
* so be sure to copy it if you need it later.
|
||||
*
|
||||
* @method Phaser.Renderer.WebGL.RenderNodes.GetQuadTransform#run
|
||||
* @since 3.90.0
|
||||
* @param {Phaser.Cameras.Scene2D.Camera} camera - The camera to use for the transformation.
|
||||
* @param {Phaser.GameObjects.GameObject} gameObject - The game object to transform.
|
||||
* @param {Phaser.GameObjects.Components.TransformMatrix} [parentTransformMatrix] - The parent matrix to apply, if any.
|
||||
* @return {Phaser.GameObjects.Components.TransformMatrix} The computed transform matrix.
|
||||
*/
|
||||
run: function (gameObject, camera, parentTransformMatrix)
|
||||
{
|
||||
var camMatrix = this._camMatrix;
|
||||
var spriteMatrix = this._spriteMatrix;
|
||||
var calcMatrix = this._calcMatrix;
|
||||
|
||||
var frame = gameObject.frame;
|
||||
var frameX = frame.x;
|
||||
var frameY = frame.y;
|
||||
var frameWidth = frame.cutWidth;
|
||||
var frameHeight = frame.cutHeight;
|
||||
var customPivot = frame.customPivot;
|
||||
|
||||
var displayOriginX = gameObject.displayOriginX;
|
||||
var displayOriginY = gameObject.displayOriginY;
|
||||
|
||||
if (gameObject.isCropped)
|
||||
{
|
||||
var crop = gameObject._crop;
|
||||
|
||||
// // TODO: This is repeated in Single; can it be eliminated?
|
||||
// // I think so: I've put it in the GameObject renderWebGL method.
|
||||
// if (crop.flipX !== gameObject.flipX || crop.flipY !== gameObject.flipY)
|
||||
// {
|
||||
// frame.updateCropUVs(crop, gameObject.flipX, gameObject.flipY);
|
||||
// }
|
||||
|
||||
frameWidth = crop.width;
|
||||
frameHeight = crop.height;
|
||||
|
||||
frameX = crop.x;
|
||||
frameY = crop.y;
|
||||
}
|
||||
|
||||
var x = -displayOriginX + frameX;
|
||||
var y = -displayOriginY + frameY;
|
||||
|
||||
var flipX = 1;
|
||||
var flipY = 1;
|
||||
|
||||
if (gameObject.flipX)
|
||||
{
|
||||
if (!customPivot)
|
||||
{
|
||||
x += (-frame.realWidth + (displayOriginX * 2));
|
||||
}
|
||||
|
||||
flipX = -1;
|
||||
}
|
||||
|
||||
if (gameObject.flipY)
|
||||
{
|
||||
if (!customPivot)
|
||||
{
|
||||
y += (-frame.realHeight + (displayOriginY * 2));
|
||||
}
|
||||
|
||||
flipY = -1;
|
||||
}
|
||||
|
||||
var gx = gameObject.x;
|
||||
var gy = gameObject.y;
|
||||
|
||||
// spriteMatrix.applyITRS(gx, gy, gameObject.rotation, gameObject.scaleX * flipX, gameObject.scaleY * flipY);
|
||||
// spriteMatrix.applyITRS(
|
||||
// gx + x,
|
||||
// gy + y,
|
||||
// gameObject.rotation,
|
||||
// frameWidth * gameObject.scaleX * flipX,
|
||||
// frameHeight * gameObject.scaleY * flipY
|
||||
// );
|
||||
spriteMatrix.applyITRS(
|
||||
x,
|
||||
y,
|
||||
0,
|
||||
frameWidth,
|
||||
frameHeight
|
||||
);
|
||||
|
||||
var newMatrix = new TransformMatrix();
|
||||
newMatrix.applyITRS(gx, gy, gameObject.rotation, gameObject.scaleX * flipX, gameObject.scaleY * flipY);
|
||||
newMatrix.multiply(spriteMatrix);
|
||||
spriteMatrix.copyFrom(newMatrix);
|
||||
// TODO: That's very complex, but it gets the right result. Can we simplify the matrix concatenation?
|
||||
|
||||
if (parentTransformMatrix)
|
||||
{
|
||||
// Multiply the camera by the parent matrix
|
||||
camMatrix.copyFrom(camera.matrix);
|
||||
camMatrix.multiplyWithOffset(parentTransformMatrix, -camera.scrollX * gameObject.scrollFactorX, -camera.scrollY * gameObject.scrollFactorY);
|
||||
|
||||
// Undo the camera scroll
|
||||
spriteMatrix.e = gx;
|
||||
spriteMatrix.f = gy;
|
||||
}
|
||||
else
|
||||
{
|
||||
// camMatrix will not be mutated after this point, so we just take a reference.
|
||||
camMatrix = camera.matrix;
|
||||
spriteMatrix.e -= camera.scrollX * gameObject.scrollFactorX;
|
||||
spriteMatrix.f -= camera.scrollY * gameObject.scrollFactorY;
|
||||
}
|
||||
|
||||
// Multiply by the Sprite matrix, store result in calcMatrix
|
||||
camMatrix.multiply(spriteMatrix, calcMatrix);
|
||||
|
||||
return calcMatrix;
|
||||
|
||||
// var quad = calcMatrix.setQuad(x, y, x + frameWidth, y + frameHeight);
|
||||
|
||||
// return quad;
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = GetQuadTransform;
|
|
@ -5,244 +5,181 @@
|
|||
*/
|
||||
|
||||
var Class = require('../../../utils/Class');
|
||||
var ShaderSourceFS = require('../shaders/Multi-frag.js');
|
||||
var ShaderSourceVS = require('../shaders/Multi-vert.js');
|
||||
var Utils = require('../Utils.js');
|
||||
var WebGLVertexBufferLayoutWrapper = require('../wrappers/WebGLVertexBufferLayoutWrapper.js');
|
||||
var Batch = require('./Batch');
|
||||
var ShaderSourceFS = require('../shaders/Multi-frag');
|
||||
var ShaderSourceVS = require('../shaders/Multi-vert');
|
||||
var Utils = require('../Utils');
|
||||
var BatchHandler = require('./BatchHandler');
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* This RenderNode draws Standard Batch Render (SBR) quads in batches.
|
||||
*
|
||||
* @class BatchTexturedTintedTransformedQuads
|
||||
* @class QuadBatchHandler
|
||||
* @extends Phaser.Renderer.WebGL.RenderNodes.Batch
|
||||
* @memberof Phaser.Renderer.WebGL.RenderNodes
|
||||
* @constructor
|
||||
* @since 3.90.0
|
||||
* @param {Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager} manager - The manager that owns this RenderNode.
|
||||
* @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - The renderer that owns this RenderNode.
|
||||
* @param {Phaser.Types.Renderer.WebGL.RenderNodes.BatchHandlerConfig} [config] - The configuration object for this handler.
|
||||
*/
|
||||
var BatchTexturedTintedTransformedQuads = new Class({
|
||||
Extends: Batch,
|
||||
var QuadBatchHandler = new Class({
|
||||
Extends: BatchHandler,
|
||||
|
||||
initialize: function BatchTexturedTintedTransformedQuads (manager, renderer)
|
||||
initialize: function QuadBatchHandler (manager, renderer, config)
|
||||
{
|
||||
Batch.call(this, 'BatchTexturedTintedTransformedQuads', manager, renderer);
|
||||
|
||||
var gl = renderer.gl;
|
||||
|
||||
/**
|
||||
* The number of quads per batch, used to determine the size of the
|
||||
* vertex and quad buffers, and the number of instances to render.
|
||||
*
|
||||
* This is usually limited by the maximum number of vertices that can be
|
||||
* distinguished with a 16-bit UNSIGNED_INT index buffer, which is 65536. It is set in the game render config.
|
||||
*
|
||||
* @name Phaser.Renderer.WebGL.RenderNodes.BatchTexturedTintedTransformedQuads#quadsPerBatch
|
||||
* @type {number}
|
||||
* @since 3.90.0
|
||||
*/
|
||||
this.quadsPerBatch = renderer.config.batchSize;
|
||||
|
||||
/**
|
||||
* The number of vertices per instance.
|
||||
* This is always 4 for a quad.
|
||||
*
|
||||
* @name Phaser.Renderer.WebGL.RenderNodes.BatchTexturedTintedTransformedQuads#verticesPerInstance
|
||||
* @type {number}
|
||||
* @since 3.90.0
|
||||
* @default 4
|
||||
*/
|
||||
this.verticesPerInstance = 4;
|
||||
|
||||
/**
|
||||
* The number of indices per instance.
|
||||
* This is always 6 for a quad.
|
||||
* It is composed of four triangles,
|
||||
* but the first and last are degenerate to allow for
|
||||
* TRIANGLE_STRIP rendering, so there are only two true triangles.
|
||||
*
|
||||
* @name Phaser.Renderer.WebGL.RenderNodes.BatchTexturedTintedTransformedQuads#indicesPerInstance
|
||||
* @type {number}
|
||||
* @since 3.90.0
|
||||
* @default 6
|
||||
*/
|
||||
this.indicesPerInstance = 6;
|
||||
|
||||
/**
|
||||
* The number of bytes per index per instance.
|
||||
* This is used to advance the index buffer, and accounts for the
|
||||
* size of a Uint16Array element.
|
||||
*
|
||||
* @name Phaser.Renderer.WebGL.RenderNodes.BatchTexturedTintedTransformedQuads#bytesPerIndexPerInstance
|
||||
* @type {number}
|
||||
* @since 3.90.0
|
||||
* @default 12
|
||||
*/
|
||||
this.bytesPerIndexPerInstance = this.indicesPerInstance * Uint16Array.BYTES_PER_ELEMENT;
|
||||
|
||||
/**
|
||||
* The maximum number of textures per batch entry.
|
||||
* This is usually the maximum number of texture units available,
|
||||
* but it might be smaller for some uses.
|
||||
*
|
||||
* @name Phaser.Renderer.WebGL.RenderNodes.BatchTexturedTintedTransformedQuads#maxTexturesPerBatch
|
||||
* @type {number}
|
||||
* @since 3.90.0
|
||||
*/
|
||||
this.maxTexturesPerBatch = manager.maxParallelTextureUnits;
|
||||
|
||||
/**
|
||||
* The number of quads currently in the batch.
|
||||
*
|
||||
* @name Phaser.Renderer.WebGL.RenderNodes.BatchTexturedTintedTransformedQuads#instanceCount
|
||||
* @type {number}
|
||||
* @since 3.90.0
|
||||
*/
|
||||
this.instanceCount = 0;
|
||||
|
||||
var ParsedShaderSourceFS = Utils.parseFragmentShaderMaxTextures(ShaderSourceFS, this.maxTexturesPerBatch);
|
||||
|
||||
/**
|
||||
* The WebGL program used to render the Game Object.
|
||||
*
|
||||
* @name Phaser.Renderer.WebGL.RenderNodes.Single#program
|
||||
* @type {Phaser.Renderer.WebGL.Wrappers.WebGLProgramWrapper}
|
||||
* @since 3.90.0
|
||||
*/
|
||||
this.program = renderer.createProgram(ShaderSourceVS, ParsedShaderSourceFS);
|
||||
|
||||
/**
|
||||
* The index buffer defining vertex order.
|
||||
*
|
||||
* @name Phaser.Renderer.WebGL.RenderNodes.BatchTexturedTintedTransformedQuads#indexBuffer
|
||||
* @type {Phaser.Renderer.WebGL.Wrappers.WebGLBufferWrapper}
|
||||
* @since 3.90.0
|
||||
*/
|
||||
this.indexBuffer = renderer.createIndexBuffer(
|
||||
this._generateElementIndices(this.quadsPerBatch),
|
||||
gl.STATIC_DRAW
|
||||
);
|
||||
|
||||
/**
|
||||
* The layout, data, and vertex buffer used to store the vertex data.
|
||||
*
|
||||
* @name Phaser.Renderer.WebGL.RenderNodes.BatchTexturedTintedTransformedQuads#vertexBufferLayout
|
||||
* @type {Phaser.Renderer.WebGL.Wrappers.WebGLVertexBufferLayoutWrapper}
|
||||
* @since 3.90.0
|
||||
*/
|
||||
this.vertexBufferLayout = new WebGLVertexBufferLayoutWrapper(
|
||||
renderer,
|
||||
this.program,
|
||||
{
|
||||
usage: gl.DYNAMIC_DRAW,
|
||||
count: this.quadsPerBatch * 4,
|
||||
layout: [
|
||||
{
|
||||
name: 'inPosition',
|
||||
location: -1,
|
||||
size: 2,
|
||||
type: gl.FLOAT,
|
||||
normalized: false
|
||||
},
|
||||
{
|
||||
name: 'inTexCoord',
|
||||
location: -1,
|
||||
size: 2,
|
||||
type: gl.FLOAT,
|
||||
normalized: false
|
||||
},
|
||||
{
|
||||
name: 'inTexId',
|
||||
location: -1,
|
||||
size: 1,
|
||||
type: gl.FLOAT,
|
||||
normalized: false
|
||||
},
|
||||
{
|
||||
name: 'inTintEffect',
|
||||
location: -1,
|
||||
size: 1,
|
||||
type: gl.FLOAT,
|
||||
normalized: false
|
||||
},
|
||||
{
|
||||
name: 'inTint',
|
||||
location: -1,
|
||||
size: 4,
|
||||
type: gl.UNSIGNED_BYTE,
|
||||
normalized: true
|
||||
}
|
||||
]
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* The Vertex Array Object used to render the batch.
|
||||
*
|
||||
* @name Phaser.Renderer.WebGL.RenderNodes.Single#vao
|
||||
* @type {Phaser.Renderer.WebGL.Wrappers.WebGLVAOWrapper}
|
||||
* @since 3.90.0
|
||||
*/
|
||||
this.vao = renderer.createVAO(this.indexBuffer, [
|
||||
this.vertexBufferLayout
|
||||
]);
|
||||
|
||||
/**
|
||||
* The current batch entry being filled with textures.
|
||||
*
|
||||
* @name Phaser.Renderer.WebGL.RenderNodes.BatchTexturedTintedTransformedQuads#currentBatchEntry
|
||||
* @type {Phaser.Types.Renderer.WebGL.WebGLPipelineBatchEntry}
|
||||
* @since 3.90.0
|
||||
*/
|
||||
this.currentBatchEntry = {
|
||||
start: 0,
|
||||
count: 0,
|
||||
unit: 0,
|
||||
texture: []
|
||||
};
|
||||
|
||||
/**
|
||||
* The entries in the batch.
|
||||
* Each entry represents a "sub-batch" of quads which use the same
|
||||
* pool of textures. This allows the renderer to continue to buffer
|
||||
* quads into the same batch without needing to upload the vertex
|
||||
* buffer. When the batch flushes, there will be one vertex buffer
|
||||
* upload, and one draw call per batch entry.
|
||||
*
|
||||
* @name Phaser.Renderer.WebGL.RenderNodes.BatchTexturedTintedTransformedQuads#batchEntries
|
||||
* @type {Phaser.Types.Renderer.WebGL.WebGLPipelineBatchEntry[]}
|
||||
* @since 3.90.0
|
||||
* @default []
|
||||
*/
|
||||
this.batchEntries = [];
|
||||
|
||||
/**
|
||||
* The number of floats per instance, used to determine how much of the vertex buffer to update.
|
||||
*
|
||||
* @name Phaser.Renderer.WebGL.RenderNodes.BatchTexturedTintedTransformedQuads#floatsPerInstance
|
||||
* @type {number}
|
||||
* @since 3.90.0
|
||||
*/
|
||||
this.floatsPerInstance = this.vertexBufferLayout.layout.stride * this.verticesPerInstance / Float32Array.BYTES_PER_ELEMENT;
|
||||
|
||||
// Set the dimension-related uniforms and listen for resize events.
|
||||
this.resize(renderer.width, renderer.height);
|
||||
this.renderer.on(Phaser.Renderer.Events.RESIZE, this.resize, this);
|
||||
BatchHandler.call(this, manager, renderer, config, this.defaultConfig);
|
||||
|
||||
// Main sampler will never change after initialization,
|
||||
// because it addresses texture units, not textures.
|
||||
this.program.setUniform('uMainSampler[0]', this.renderer.textureUnitIndices);
|
||||
},
|
||||
|
||||
// Listen for changes to the number of draw calls per batch.
|
||||
this.manager.on(Phaser.Renderer.Events.SET_PARALLEL_TEXTURE_UNITS, this.updateTextureCount, this);
|
||||
defaultConfig: {
|
||||
name: 'QuadBatchHandler',
|
||||
verticesPerInstance: 4,
|
||||
indicesPerInstance: 6,
|
||||
vertexSource: ShaderSourceVS,
|
||||
fragmentSource: ShaderSourceFS,
|
||||
vertexBufferLayout: {
|
||||
usage: 'DYNAMIC_DRAW',
|
||||
layout: [
|
||||
{
|
||||
name: 'inPosition',
|
||||
size: 2
|
||||
},
|
||||
{
|
||||
name: 'inTexCoord',
|
||||
size: 2
|
||||
},
|
||||
{
|
||||
name: 'inTexId'
|
||||
},
|
||||
{
|
||||
name: 'inTintEffect'
|
||||
},
|
||||
{
|
||||
name: 'inTint',
|
||||
size: 4,
|
||||
type: 'UNSIGNED_BYTE',
|
||||
normalized: true
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Generate element indices for the instance vertices.
|
||||
* This is called automatically when the node is initialized.
|
||||
*
|
||||
* By default, each instance is a quad.
|
||||
* Each quad is drawn as two triangles, with the vertices in the order:
|
||||
* 0, 0, 1, 2, 3, 3. The quads are drawn as a TRIANGLE_STRIP, so the
|
||||
* repeated vertices form degenerate triangles to connect the quads
|
||||
* without being drawn.
|
||||
*
|
||||
* @method Phaser.Renderer.WebGL.RenderNodes.BatchHandler#_generateElementIndices
|
||||
* @since 3.90.0
|
||||
* @private
|
||||
* @param {number} instances - The number of instances to define.
|
||||
* @return {Uint16Array} The index buffer data.
|
||||
*/
|
||||
_generateElementIndices: function (instances)
|
||||
{
|
||||
var indices = new Uint16Array(instances * 6);
|
||||
var offset = 0;
|
||||
for (var i = 0; i < instances; i++)
|
||||
{
|
||||
var index = i * 4;
|
||||
indices[offset++] = index;
|
||||
indices[offset++] = index;
|
||||
indices[offset++] = index + 1;
|
||||
indices[offset++] = index + 2;
|
||||
indices[offset++] = index + 3;
|
||||
indices[offset++] = index + 3;
|
||||
}
|
||||
return indices;
|
||||
},
|
||||
|
||||
/**
|
||||
* Set new dimensions for the renderer. This is called automatically when the renderer is resized.
|
||||
*
|
||||
* @method Phaser.Renderer.WebGL.RenderNodes.BatchTexturedTintedTransformedQuads#resize
|
||||
* @since 3.90.0
|
||||
* @param {number} width - The new width of the renderer.
|
||||
* @param {number} height - The new height of the renderer.
|
||||
*/
|
||||
resize: function (width, height)
|
||||
{
|
||||
this.program.setUniform('uResolution', [ width, height ]);
|
||||
this.program.setUniform('uProjectionMatrix', this.renderer.projectionMatrix.val);
|
||||
},
|
||||
|
||||
/**
|
||||
* Update the number of draw calls per batch.
|
||||
* This rebuilds the shader program with the new draw call count.
|
||||
* The minimum number of draw calls is 1, and the maximum is the number of
|
||||
* texture units defined in the renderer.
|
||||
* Rebuilding the shader may be expensive, so use this sparingly.
|
||||
*
|
||||
* If this runs during a batch, and the new count is less than the number of
|
||||
* textures in the current batch entry, the batch will be flushed before the
|
||||
* shader program is rebuilt, so none of the textures are skipped.
|
||||
*
|
||||
* This is usually called automatically by a listener
|
||||
* for the `Phaser.Renderer.Events.SET_PARALLEL_TEXTURE_UNITS` event,
|
||||
* triggered by the RenderNodeManager.
|
||||
*
|
||||
* @method Phaser.Renderer.WebGL.RenderNodes.Pressurizer#updateTextureCount
|
||||
* @since 3.90.0
|
||||
* @param {number} [count] - The new number of draw calls per batch. If undefined, the maximum number of texture units is used.
|
||||
*/
|
||||
updateTextureCount: function (count)
|
||||
{
|
||||
if (count === undefined)
|
||||
{
|
||||
count = this.renderer.maxTextures;
|
||||
}
|
||||
|
||||
var newCount = Math.max(1, Math.min(count, this.renderer.maxTextures));
|
||||
if (newCount === this.texturesPerBatch)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
newCount < this.currentBatchEntry.unit &&
|
||||
this.manager.currentBatchNode === this
|
||||
)
|
||||
{
|
||||
// The batch is currently running. Flush the current batch entry,
|
||||
// before the shader program becomes unable to handle all textures.
|
||||
this.manager.setCurrentBatchNode(null);
|
||||
}
|
||||
|
||||
this.maxTexturesPerBatch = newCount;
|
||||
|
||||
// Recreate the shader program with the new texture count.
|
||||
this.program.fragmentSource = Utils.parseFragmentShaderMaxTextures(
|
||||
this.rawShaderSourceFS,
|
||||
this.maxTexturesPerBatch
|
||||
);
|
||||
this.program.createResource();
|
||||
|
||||
this.program.setUniform(
|
||||
'uMainSampler[0]',
|
||||
this.renderer.textureUnitIndices
|
||||
);
|
||||
this.resize(this.renderer.width, this.renderer.height);
|
||||
},
|
||||
|
||||
/**
|
||||
* Draw then empty the current batch.
|
||||
*
|
||||
* @method Phaser.Renderer.WebGL.RenderNodes.BatchTexturedTintedTransformedQuads#run
|
||||
* This method is called automatically, by either this node or the manager,
|
||||
* when the batch is full, or when something else needs to be rendered.
|
||||
*
|
||||
* @method Phaser.Renderer.WebGL.RenderNodes.BatchHandler#run
|
||||
* @since 3.90.0
|
||||
* @param {Phaser.Types.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context.
|
||||
*/
|
||||
|
@ -261,7 +198,7 @@ var BatchTexturedTintedTransformedQuads = new Class({
|
|||
this.pushCurrentBatchEntry();
|
||||
|
||||
// Update vertex buffers.
|
||||
if (this.instanceCount < this.quadsPerBatch)
|
||||
if (this.instanceCount < this.instancesPerBatch)
|
||||
{
|
||||
// We use a subarray to avoid copying the buffer, but still
|
||||
// control the length.
|
||||
|
@ -305,7 +242,7 @@ var BatchTexturedTintedTransformedQuads = new Class({
|
|||
* - Top-right
|
||||
* - Bottom-right
|
||||
*
|
||||
* @method Phaser.Renderer.WebGL.RenderNodes.BatchTexturedTintedTransformedQuads#batch
|
||||
* @method Phaser.Renderer.WebGL.RenderNodes.BatchHandler#batch
|
||||
* @since 3.90.0
|
||||
* @param {Phaser.Types.Renderer.WebGL.DrawingContext} currentContext - The current drawing context.
|
||||
* @param {Phaser.Renderer.WebGL.WebGLTextureWrapper} glTexture - The texture to render.
|
||||
|
@ -407,7 +344,7 @@ var BatchTexturedTintedTransformedQuads = new Class({
|
|||
|
||||
// Check whether the batch should be rendered immediately.
|
||||
// This guarantees that none of the arrays are full above.
|
||||
if (this.instanceCount === this.quadsPerBatch)
|
||||
if (this.instanceCount === this.instancesPerBatch)
|
||||
{
|
||||
this.run(currentContext);
|
||||
|
||||
|
@ -419,7 +356,7 @@ var BatchTexturedTintedTransformedQuads = new Class({
|
|||
* Push the current batch entry to the batch entry list,
|
||||
* and create a new batch entry for future use.
|
||||
*
|
||||
* @method Phaser.Renderer.WebGL.RenderNodes.BatchTexturedTintedTransformedQuads#pushCurrentBatchEntry
|
||||
* @method Phaser.Renderer.WebGL.RenderNodes.BatchHandler#pushCurrentBatchEntry
|
||||
* @since 3.90.0
|
||||
*/
|
||||
pushCurrentBatchEntry: function ()
|
||||
|
@ -439,112 +376,7 @@ var BatchTexturedTintedTransformedQuads = new Class({
|
|||
unit: 0,
|
||||
texture: []
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Generate element indices for the quad vertices.
|
||||
* This is called automatically when the node is initialized.
|
||||
*
|
||||
* Each quad is drawn as two triangles, with the vertices in the order:
|
||||
* 0, 0, 1, 2, 3, 3. The quads are drawn as a TRIANGLE_STRIP, so the
|
||||
* repeated vertices form degenerate triangles to connect the quads
|
||||
* without being drawn.
|
||||
*
|
||||
* @method Phaser.Renderer.WebGL.RenderNodes.BatchTexturedTintedTransformedQuads#_generateElementIndices
|
||||
* @since 3.90.0
|
||||
* @private
|
||||
* @param {number} quads - The number of quads to define.
|
||||
* @return {Uint16Array} The index buffer data.
|
||||
*/
|
||||
_generateElementIndices: function (quads)
|
||||
{
|
||||
var indices = new Uint16Array(quads * 6);
|
||||
var offset = 0;
|
||||
for (var i = 0; i < quads; i++)
|
||||
{
|
||||
var index = i * 4;
|
||||
indices[offset++] = index;
|
||||
indices[offset++] = index;
|
||||
indices[offset++] = index + 1;
|
||||
indices[offset++] = index + 2;
|
||||
indices[offset++] = index + 3;
|
||||
indices[offset++] = index + 3;
|
||||
}
|
||||
return indices;
|
||||
},
|
||||
|
||||
/**
|
||||
* Set new dimensions for the renderer. This is called automatically when the renderer is resized.
|
||||
*
|
||||
* @method Phaser.Renderer.WebGL.RenderNodes.BatchTexturedTintedTransformedQuads#resize
|
||||
* @since 3.90.0
|
||||
* @param {number} width - The new width of the renderer.
|
||||
* @param {number} height - The new height of the renderer.
|
||||
*/
|
||||
resize: function (width, height)
|
||||
{
|
||||
this.program.setUniform('uResolution', [ width, height ]);
|
||||
this.program.setUniform('uProjectionMatrix', this.renderer.projectionMatrix.val);
|
||||
},
|
||||
|
||||
/**
|
||||
* Update the number of draw calls per batch.
|
||||
* This rebuilds the shader program with the new draw call count.
|
||||
* The minimum number of draw calls is 1, and the maximum is the number of
|
||||
* texture units defined in the renderer.
|
||||
* Rebuilding the shader may be expensive, so use this sparingly.
|
||||
*
|
||||
* If this runs during a batch, and the new count is less than the number of
|
||||
* textures in the current batch entry, the batch will be flushed before the
|
||||
* shader program is rebuilt, so none of the textures are skipped.
|
||||
*
|
||||
* This is usually called automatically by a listener
|
||||
* for the `Phaser.Renderer.Events.SET_PARALLEL_TEXTURE_UNITS` event,
|
||||
* triggered by the RenderNodeManager.
|
||||
*
|
||||
* @method Phaser.Renderer.WebGL.RenderNodes.Pressurizer#updateTextureCount
|
||||
* @since 3.90.0
|
||||
* @param {number} [count] - The new number of draw calls per batch. If undefined, the maximum number of texture units is used.
|
||||
*/
|
||||
updateTextureCount: function (count)
|
||||
{
|
||||
if (count === undefined)
|
||||
{
|
||||
count = this.renderer.maxTextures;
|
||||
}
|
||||
|
||||
var newCount = Math.max(1, Math.min(count, this.renderer.maxTextures));
|
||||
if (newCount === this.texturesPerBatch)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
newCount < this.currentBatchEntry.unit &&
|
||||
this.manager.currentBatchNode === this
|
||||
)
|
||||
{
|
||||
// The batch is currently running. Flush the current batch entry,
|
||||
// before the shader program becomes unable to handle all textures.
|
||||
this.manager.setCurrentBatchNode(null);
|
||||
}
|
||||
|
||||
this.maxTexturesPerBatch = newCount;
|
||||
|
||||
// Recreate the shader program with the new texture count.
|
||||
var ParsedShaderSourceFS = Utils.parseFragmentShaderMaxTextures(
|
||||
ShaderSourceFS,
|
||||
this.maxTexturesPerBatch
|
||||
);
|
||||
this.program.fragmentSource = ParsedShaderSourceFS;
|
||||
this.program.createResource();
|
||||
|
||||
this.program.setUniform(
|
||||
'uMainSampler[0]',
|
||||
this.renderer.textureUnitIndices
|
||||
);
|
||||
this.resize(this.renderer.width, this.renderer.height);
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = BatchTexturedTintedTransformedQuads;
|
||||
module.exports = QuadBatchHandler;
|
|
@ -7,12 +7,13 @@
|
|||
var EventEmitter = require('eventemitter3');
|
||||
var Class = require('../../../utils/Class');
|
||||
var Events = require('../../events');
|
||||
var BatchTexturedTintedTransformedQuads = require('./BatchTexturedTintedTransformedQuads');
|
||||
|
||||
var Camera = require('./Camera');
|
||||
var FillCamera = require('./FillCamera');
|
||||
var FillRect = require('./FillRect');
|
||||
var ImageQuadrangulateBatch = require('./ImageQuadrangulateBatch');
|
||||
var GameObjectBatcher = require('./GameObjectBatcher');
|
||||
var ListCompositor = require('./ListCompositor');
|
||||
var QuadBatchHandler = require('./QuadBatchHandler');
|
||||
|
||||
/**
|
||||
* @typedef {object} DebugGraphNode
|
||||
|
@ -69,21 +70,56 @@ var RenderNodeManager = new Class({
|
|||
this.maxParallelTextureUnits = (game.config.autoMobilePipeline && !game.device.os.desktop) ? 1 : renderer.maxTextures;
|
||||
|
||||
/**
|
||||
* Nodes available for use.
|
||||
* Nodes available for use. This is an internal object,
|
||||
* where the keys are the names of the nodes.
|
||||
*
|
||||
* @name Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager#steps
|
||||
* Nodes are constructed when requested by `getNode`.
|
||||
* Custom nodes can be added via `addNode` or `addNodeConstructor`.
|
||||
*
|
||||
* @name Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager#nodes
|
||||
* @type {object}
|
||||
* @since 3.90.0
|
||||
* @private
|
||||
*/
|
||||
this.nodes = {
|
||||
BatchTexturedTintedTransformedQuads: new BatchTexturedTintedTransformedQuads(this, renderer),
|
||||
Camera: new Camera(this, renderer),
|
||||
FillCamera: new FillCamera(this, renderer),
|
||||
FillRect: new FillRect(this, renderer),
|
||||
ImageQuadrangulateBatch: new ImageQuadrangulateBatch(this, renderer),
|
||||
ListCompositor: new ListCompositor(this, renderer),
|
||||
this._nodes = {};
|
||||
|
||||
/**
|
||||
* Built-in nodes which can be constructed by name.
|
||||
* Use `getNode` to either return a constructed built-in node
|
||||
* from `_nodes`, or construct a new one if it does not exist.
|
||||
*
|
||||
* Use `addNodeConstructor` to add custom nodes
|
||||
* without constructing them.
|
||||
* Use `addNode` to add custom nodes that have already been constructed.
|
||||
*
|
||||
* @name Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager#_nodeConstructors
|
||||
* @type {object}
|
||||
* @since 3.90.0
|
||||
* @private
|
||||
*/
|
||||
this._nodeConstructors = {
|
||||
Camera: Camera,
|
||||
FillCamera: FillCamera,
|
||||
FillRect: FillRect,
|
||||
GameObjectBatcher: GameObjectBatcher,
|
||||
ImageQuadrangulateBatch: ImageQuadrangulateBatch,
|
||||
ListCompositor: ListCompositor,
|
||||
QuadBatchHandler: QuadBatchHandler
|
||||
};
|
||||
|
||||
/**
|
||||
* The default node to use for game objects.
|
||||
*
|
||||
* By default, this is the GameObjectBatcher node.
|
||||
* It is specified as a string, so that the node is only constructed
|
||||
* when it is needed.
|
||||
*
|
||||
* @name Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager#default
|
||||
* @type {string}
|
||||
* @since 3.90.0
|
||||
*/
|
||||
this.default = GameObjectBatcher.name;
|
||||
|
||||
/**
|
||||
* The RenderNode which is currently being filled.
|
||||
* This is stored so that it can be completed when another type of
|
||||
|
@ -149,11 +185,11 @@ var RenderNodeManager = new Class({
|
|||
*/
|
||||
addNode: function (name, node)
|
||||
{
|
||||
if (this.nodes[name])
|
||||
if (this._nodes[name])
|
||||
{
|
||||
throw new Error('node ' + name + ' already exists.');
|
||||
}
|
||||
this.nodes[name] = node;
|
||||
this._nodes[name] = node;
|
||||
|
||||
// If a node is somehow added during a debug render pass,
|
||||
// ensure that it is also set to debug.
|
||||
|
@ -163,6 +199,70 @@ var RenderNodeManager = new Class({
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Add a constructor for a node to the manager.
|
||||
* This will allow the node to be constructed when `getNode` is called.
|
||||
*
|
||||
* @method Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager#addNodeConstructor
|
||||
* @since 3.90.0
|
||||
* @param {string} name - The name of the node.
|
||||
* @param {function} constructor - The constructor for the node.
|
||||
* @throws {Error} Will throw an error if the node constructor already exists.
|
||||
*/
|
||||
addNodeConstructor: function (name, constructor)
|
||||
{
|
||||
if (this._nodeConstructors[name])
|
||||
{
|
||||
throw new Error('node constructor ' + name + ' already exists.');
|
||||
}
|
||||
this._nodeConstructors[name] = constructor;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get a node from the manager.
|
||||
*
|
||||
* If the node does not exist, and a constructor is available,
|
||||
* it will be constructed and added to the manager,
|
||||
* then returned.
|
||||
*
|
||||
* @method Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager#getNode
|
||||
* @since 3.90.0
|
||||
* @param {string} name - The name of the node.
|
||||
* @return {?Phaser.Renderer.WebGL.RenderNodes.RenderNode} The node, or null if it does not exist.
|
||||
*/
|
||||
getNode: function (name)
|
||||
{
|
||||
if (this._nodes[name])
|
||||
{
|
||||
return this._nodes[name];
|
||||
}
|
||||
if (this._nodeConstructors[name])
|
||||
{
|
||||
var node = new this._nodeConstructors[name](this, this.renderer);
|
||||
this.addNode(name, node);
|
||||
return node;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Check if a node exists in the manager.
|
||||
*
|
||||
* If a node is not constructed, but a constructor is available,
|
||||
* it will be considered to exist. Set `constructed` to true to
|
||||
* require that the node has already been constructed.
|
||||
*
|
||||
* @method Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager#hasNode
|
||||
* @since 3.90.0
|
||||
* @param {string} name - The name of the node.
|
||||
* @param {boolean} [constructed=false] - Whether the node must be constructed to be considered to exist.
|
||||
* @return {boolean} Whether the node exists.
|
||||
*/
|
||||
hasNode: function (name, constructed)
|
||||
{
|
||||
return !!this._nodes[name] || (!constructed && !!this._nodeConstructors[name]);
|
||||
},
|
||||
|
||||
/**
|
||||
* Set the current batch node. If a batch node is already in progress,
|
||||
* it will be completed before the new node is set.
|
||||
|
@ -233,9 +333,9 @@ var RenderNodeManager = new Class({
|
|||
{
|
||||
this.debug = value;
|
||||
|
||||
for (var key in this.nodes)
|
||||
for (var key in this._nodes)
|
||||
{
|
||||
this.nodes[key].setDebug(value);
|
||||
this._nodes[key].setDebug(value);
|
||||
}
|
||||
|
||||
if (value)
|
||||
|
|
|
@ -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}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {object} Phaser.Types.Renderer.WebGL.RenderNodes.BatchHandlerConfig
|
||||
* @since 3.90.0
|
||||
*
|
||||
* @property {string} name - The name of the RenderNode. This should be unique within the manager.
|
||||
* @property {number} [instancesPerBatch] - The number of instances per batch. Instances are usually quads. This factors into the size of the vertex buffer. The default is based on 16-bit vertex indices, which allows for 65535 vertices. This is divided by `verticesPerInstance` to get the number of instances. Note that no larger number of vertices is possible with 16-bit indices.
|
||||
* @property {number} [verticesPerInstance=4] - The number of unique vertices per instance. This is usually 4 for a quad.
|
||||
* @property {number} [indicesPerInstance=6] - The number of indices per instance. This is used to populate and advance the element buffer. Default quads use 6 indices in the TRIANGLE_STRIP pattern [0, 0, 1, 2, 3, 3] to connect independent quads with degenerate topology. The minimum number is 3.
|
||||
* @property {number} [maxTexturesPerBatch] - The maximum number of textures per batch entry. This defaults to the maximum number of textures supported by the renderer. It is used to compile the shader program. At runtime, the manager may suggest a different number, which is interpreted by the node's `updateTextureCount` method.
|
||||
* @property {string} [vertexSource] - The vertex shader source code. If not provided, a default quad shader will be used.
|
||||
* @property {string} [fragmentSource] - The fragment shader source code. If not provided, a default quad shader will be used. The fragment shader will be compiled
|
||||
* @property {Partial<Phaser.Types.Renderer.WebGL.WebGLAttributeBufferLayout>} [vertexBufferLayout] - The vertex buffer layout for the batch handler. If not provided, a default quad layout will be used. The `count` property will be determined by the `instancesPerBatch` and `verticesPerInstance` properties. The `location` and `bytes` properties of each attribute will be determined automatically during initialization.
|
||||
* @property {string[]} [vertexBufferLayoutRemove] - An array of attribute names to remove from the vertex buffer layout. This is useful for removing attributes that are not used by the shader program.
|
||||
* @property {Partial<Phaser.Types.Renderer.WebGL.WebGLAttributeLayout>[]} [vertexBufferLayoutAdd] - An array of additional attribute layouts to add to the vertex buffer layout. This is useful for adding attributes to the default shader program.
|
||||
*/
|
|
@ -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}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {object} Phaser.Types.Renderer.WebGL.RenderNodes.GameObjectBatcherConfig
|
||||
* @since 3.90.0
|
||||
*
|
||||
* @property {string} name - The name of the RenderNode. This should be unique within the manager.
|
||||
* @property {string|Phaser.Renderer.WebGL.RenderNodes.BatchHandler} [batchHandler='QuadBatchHandler'] - The batch handler to which this node will send vertex information. The batch handler will be added to the manager if necessary. This is invoked during `run`. It is where shader configuration should be done.
|
||||
*/
|
21
src/renderer/webgl/renderNodes/index.js
Normal file
21
src/renderer/webgl/renderNodes/index.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}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @namespace Phaser.Types.Renderer.WebGL.RenderNodes
|
||||
*/
|
||||
|
||||
var RenderNodes = {
|
||||
BatchHandler: require('./BatchHandler'),
|
||||
Camera: require('./Camera'),
|
||||
FillCamera: require('./FillCamera'),
|
||||
FillRect: require('./FillRect'),
|
||||
GameObjectBatcher: require('./GameObjectBatcher'),
|
||||
QuadBatchHandler: require('./QuadBatchHandler'),
|
||||
RenderNode: require('./RenderNode')
|
||||
};
|
||||
|
||||
module.exports = RenderNodes;
|
|
@ -11,7 +11,7 @@
|
|||
* @property {string} name - The name of the attribute, as defined in the shader.
|
||||
* @property {Phaser.Renderer.WebGL.Wrappers.WebGLAttribLocationWrapper} location - The location of the attribute.
|
||||
* @property {number} size - The number of components per vertex attribute.
|
||||
* @property {GLenum} type - The data type of each component in the array. This can differ from the type in the shader, so long as WebGL can convert the types.
|
||||
* @property {GLenum|string} type - The data type of each component in the array. This can differ from the type in the shader, so long as WebGL can convert the types. If the type is a string, it will be converted to the appropriate GLenum, e.g. 'FLOAT' to gl.FLOAT.
|
||||
* @property {boolean} normalized - Whether integer data values should be normalized when being cast to a float.
|
||||
* @property {number} offset - The byte offset from the beginning of the buffer.
|
||||
* @property {number} [bytes=4] - The number of bytes per vertex attribute. This is the size of the type, usually 4 bytes for FLOAT or INT.
|
||||
|
@ -24,6 +24,6 @@
|
|||
*
|
||||
* @property {number} stride - The stride of the attribute data.
|
||||
* @property {number} count - The maximum number of elements in the buffer.
|
||||
* @property {GLenum} usage - The usage pattern of the data store. gl.STATIC_DRAW, gl.DYNAMIC_DRAW or gl.STREAM_DRAW.
|
||||
* @property {GLenum|string} usage - The usage pattern of the data store. gl.STATIC_DRAW, gl.DYNAMIC_DRAW or gl.STREAM_DRAW. If the type is a string, it will be converted to the appropriate GLenum, e.g. 'STATIC_DRAW' to gl.STATIC_DRAW.
|
||||
* @property {Phaser.Types.Renderer.WebGL.WebGLAttributeLayout} layout - The layout of the attribute data.
|
||||
*/
|
||||
|
|
|
@ -318,6 +318,8 @@ var WebGLProgramWrapper = new Class({
|
|||
/**
|
||||
* Complete the layout of the provided attribute buffer layout.
|
||||
* This will fill in the stride, locations, byte counts, and offsets.
|
||||
* In addition, it will convert any GLenums specified as strings
|
||||
* to their numeric values.
|
||||
* This mutates the layout.
|
||||
*
|
||||
* The order of attributes within the layout forms the order of the buffer.
|
||||
|
@ -330,11 +332,17 @@ var WebGLProgramWrapper = new Class({
|
|||
*/
|
||||
completeLayout: function (attributeBufferLayout)
|
||||
{
|
||||
var gl = this.renderer.gl;
|
||||
var layout = attributeBufferLayout.layout;
|
||||
var glAttributes = this.glAttributes;
|
||||
var glAttributeNames = this.glAttributeNames;
|
||||
var constants = this.renderer.shaderSetters.constants;
|
||||
|
||||
if (typeof attributeBufferLayout.usage === 'string')
|
||||
{
|
||||
attributeBufferLayout.usage = gl[attributeBufferLayout.usage];
|
||||
}
|
||||
|
||||
var offset = 0;
|
||||
|
||||
for (var i = 0; i < layout.length; i++)
|
||||
|
@ -346,6 +354,12 @@ var WebGLProgramWrapper = new Class({
|
|||
// First, append the current offset.
|
||||
attribute.offset = offset;
|
||||
|
||||
// Convert the type to a GLenum if it is a string.
|
||||
if (typeof attribute.type === 'string')
|
||||
{
|
||||
attribute.type = gl[attribute.type];
|
||||
}
|
||||
|
||||
var typeData = constants[attribute.type];
|
||||
var baseSize = typeData.size;
|
||||
var baseBytes = typeData.bytes;
|
||||
|
|
|
@ -18,7 +18,7 @@ var Class = require('../../../utils/Class');
|
|||
* @since 3.90.0
|
||||
* @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - The WebGLRenderer instance that owns this wrapper.
|
||||
* @param {Phaser.Renderer.WebGL.Wrappers.WebGLProgramWrapper} program - The program that this layout is associated with.
|
||||
* @param {Partial<Phaser.Types.Renderer.WebGL.WebGLBufferLayout>} layout - The layout of the buffer. At construction, this should be incomplete. The stride and per-attribute location, bytes, and offset will be filled in during construction. This will mutate the object.
|
||||
* @param {Partial<Phaser.Types.Renderer.WebGL.WebGLAttributeBufferLayout>} layout - The layout of the buffer. At construction, this should be incomplete. The stride and per-attribute location, bytes, and offset will be filled in during construction. This will mutate the object.
|
||||
*/
|
||||
var WebGLVertexBufferLayoutWrapper = new Class({
|
||||
initialize: function WebGLVertexBufferLayoutWrapper (renderer, program, layout)
|
||||
|
@ -45,7 +45,7 @@ var WebGLVertexBufferLayoutWrapper = new Class({
|
|||
* The layout of the buffer.
|
||||
*
|
||||
* @name Phaser.Renderer.WebGL.Wrappers.WebGLVertexBufferLayoutWrapper#layout
|
||||
* @type {Phaser.Types.Renderer.WebGL.WebGLBufferLayout}
|
||||
* @type {Phaser.Types.Renderer.WebGL.WebGLAttributeBufferLayout}
|
||||
* @since 3.90.0
|
||||
*/
|
||||
this.layout = layout;
|
||||
|
|
Loading…
Reference in a new issue