@awayjs/renderer
Version:
Renderer for AwayJS
286 lines (285 loc) • 13.5 kB
JavaScript
import { __extends } from "tslib";
import { AssetEvent, Matrix3D, PerspectiveProjection, } from '@awayjs/core';
import { AttributesBuffer, Image2D, ContextGLTriangleFace, StageEvent, ImageSampler } from '@awayjs/stage';
import { ContainerNodeEvent, HierarchicalProperty, PickGroup } from '@awayjs/view';
import { _Render_RenderableBase } from './base/_Render_RenderableBase';
import { _Render_RendererMaterial } from './base/_Render_RendererMaterial';
import { TriangleElements } from './elements/TriangleElements';
import { MaterialEvent } from './events/MaterialEvent';
import { RendererBase } from './RendererBase';
import { RenderGroup } from './RenderGroup';
import { ImageTexture2D } from './textures/ImageTexture2D';
import { Settings as StageSettings } from '@awayjs/stage';
import { RenderEntity } from './base/RenderEntity';
import { DefaultRenderer } from './DefaultRenderer';
var CacheRenderer = /** @class */ (function (_super) {
__extends(CacheRenderer, _super);
function CacheRenderer() {
var _this = _super.call(this) || this;
_this._textures = [];
_this.animateUVs = false;
_this.bothSides = false;
_this.curves = false;
_this.imageRect = false;
_this.useColorTransform = true;
_this.alphaBlending = true;
_this.alphaThreshold = 0;
_this._onTextureInvalidate = function (event) { return _this.invalidate(); };
_this._onInvalidateSceneTransform = function (event) { return _this.onInvalidateSceneTransform(); };
_this._onInvalidateColorTransform = function (event) { return _this.onInvalidateColorTransform(); };
_this._traverserGroup = RenderGroup.getInstance(CacheRenderer);
_this._maskGroup = RenderGroup.getInstance(DefaultRenderer);
return _this;
}
Object.defineProperty(CacheRenderer.prototype, "assetType", {
get: function () {
return CacheRenderer.assetType;
},
enumerable: false,
configurable: true
});
Object.defineProperty(CacheRenderer.prototype, "texture", {
/**
* The 2d texture to use as a bitmap cache.
*/
get: function () {
//TODO check invalidation of _texture
return this._texture;
},
set: function (value) {
if (this._texture == value)
return;
if (this._texture)
this.removeTexture(this._texture);
this._texture = value;
if (this._texture)
this.addTexture(this._texture);
this.invalidatePasses();
},
enumerable: false,
configurable: true
});
CacheRenderer.prototype._onInvalidateElements = function () {
// for (const key in this._abstractionPool)
// (this._abstractionPool[key] as _Render_RenderableBase)._onInvalidateElements();
};
CacheRenderer.prototype._onInvalidateMaterial = function () {
// for (const key in this._abstractionPool)
// (this._abstractionPool[key] as _Render_RenderableBase)._onInvalidateMaterial();
};
CacheRenderer.prototype.init = function (node, group) {
_super.prototype.init.call(this, node, group);
node.view.stage.addEventListener(StageEvent.INVALIDATE_SIZE, this._onSizeInvalidateDelegate);
if (this._parentNode) {
this._parentNode.addEventListener(ContainerNodeEvent.INVALIDATE_MATRIX3D, this._onInvalidateSceneTransform);
this._parentNode.addEventListener(ContainerNodeEvent.INVALIDATE_COLOR_TRANSFORM, this._onInvalidateColorTransform);
}
// for check filters/blends changes
node.container._renderObjects[group.id] = this;
this.texture = new ImageTexture2D();
};
CacheRenderer.prototype.render = function (enableDepthAndStencil, surfaceSelector, mipmapSelector, maskConfig) {
if (enableDepthAndStencil === void 0) { enableDepthAndStencil = true; }
if (surfaceSelector === void 0) { surfaceSelector = 0; }
if (mipmapSelector === void 0) { mipmapSelector = 0; }
if (maskConfig === void 0) { maskConfig = 0; }
var container = this.node.container;
var stage = this.stage;
var useNonNativeBlend = this.useNonNativeBlend;
var targetImage = (useNonNativeBlend ? this.parentRenderer.style.image : this._style.image);
if (!targetImage) {
return _super.prototype.render.call(this, enableDepthAndStencil, surfaceSelector, mipmapSelector, maskConfig);
}
// WE MUST store older render target config,
// because node can have cached child, that can be filtered
this.stage.pushRenderTargetConfig();
var msaa = stage.context.glVersion === 2 && StageSettings.ENABLE_MULTISAMPLE_TEXTURE;
// we not require use TMP texture when not have MSAA
var sourceImage = (msaa)
? stage.filterManager.popTemp(targetImage.width, targetImage.height, true)
: targetImage;
//for DefaultRenderer when child has a blendmode applied
if (useNonNativeBlend) {
var proj = this.parentRenderer.view.projection;
this.parentRenderer.view.projection = new PerspectiveProjection();
this.parentRenderer.view.target = targetImage;
//this.parentRenderer.disableClear = true;
this.parentRenderer._initRender(targetImage);
this.parentRenderer.executeRender();
this.parentRenderer.resetHead();
//this.parentRenderer.disableClear = false;
this.parentRenderer.view.target = null;
this.parentRenderer.view.projection = proj;
this._disableClear = true;
}
this._initRender(sourceImage);
_super.prototype.render.call(this, enableDepthAndStencil, surfaceSelector, mipmapSelector, maskConfig);
if (targetImage.width * targetImage.height === 0) {
throw new Error('Cannot have image with size 0 * 0');
}
//@ts-ignore
var filters = container.filters;
var scale = this.getBoundsScale();
if (filters && filters.length > 0) {
filters.forEach(function (e) { return e && (e.imageScale = scale); });
stage.filterManager.applyFilters(sourceImage, targetImage, // because we use source as filter target - we not require copy
targetImage.rect, targetImage.rect, filters);
}
else if (msaa) {
// this is fast, it should only call blitFramebuffer,
// same as in regular MSAA
stage.filterManager.copyPixels(sourceImage, targetImage, targetImage.rect, targetImage.rect.topLeft, useNonNativeBlend, useNonNativeBlend ? container.blendMode : '');
}
if (msaa) {
stage.filterManager.pushTemp(sourceImage);
}
// pop render target after any filters,
// required for deep filters (when node with filter has filtered child)
this.stage.popRenderTarget();
};
CacheRenderer.prototype._updateBounds = function () {
_super.prototype._updateBounds.call(this);
var image = this._style.image;
var pad = this._paddedBounds;
if (image) {
this._style.image._setSize(pad.width, pad.height);
}
else {
this._style.image = new Image2D(pad.width, pad.height, false);
this._style.sampler = new ImageSampler(false, false, false);
//this._view.target = this._style.image;
}
};
// apply blend modes and swap texture if needed
CacheRenderer.prototype.preActivateRenderPass = function () {
};
CacheRenderer.prototype.getNumTextures = function () {
return this._textures.length;
};
CacheRenderer.prototype.getTextureAt = function (index) {
return this._textures[index];
};
CacheRenderer.prototype.addTexture = function (texture) {
this._textures.push(texture);
texture.addEventListener(AssetEvent.INVALIDATE, this._onTextureInvalidate);
this.invalidate();
};
CacheRenderer.prototype.removeTexture = function (texture) {
this._textures.splice(this._textures.indexOf(texture), 1);
texture.removeEventListener(AssetEvent.INVALIDATE, this._onTextureInvalidate);
this.invalidate();
};
/**
* Marks the shader programs for all passes as invalid, so they will be recompiled before the next use.
*
* @private
*/
CacheRenderer.prototype.invalidatePasses = function () {
this.dispatchEvent(new MaterialEvent(MaterialEvent.INVALIDATE_PASSES, this));
};
/**
*
*/
CacheRenderer.prototype.enterNode = function (node) {
var enter = _super.prototype.enterNode.call(this, node);
if (enter && node.boundsVisible)
this.applyEntity(node.getBoundsPrimitive(PickGroup.getInstance()));
return enter;
};
CacheRenderer.prototype.onInvalidate = function () {
_super.prototype.onInvalidate.call(this);
for (var key in this._renderObjects)
this._renderObjects[key]._onInvalidateElements();
for (var key in this._renderObjects)
this._renderObjects[key]._onInvalidateStyle();
this.invalidate();
this.invalidatePasses();
};
CacheRenderer.prototype.onInvalidateSceneTransform = function () {
this._asset.invalidateHierarchicalProperty(HierarchicalProperty.SCENE_TRANSFORM);
this.onInvalidate();
};
CacheRenderer.prototype.onInvalidateColorTransform = function () {
this._asset.invalidateHierarchicalProperty(HierarchicalProperty.COLOR_TRANSFORM);
this.invalidate();
};
CacheRenderer.prototype.onClear = function () {
this.removeTexture(this._texture);
this._texture.clear();
this._texture = null;
this._style.image.clear();
this._style.image = null;
this._asset.view.stage.removeEventListener(StageEvent.INVALIDATE_SIZE, this._onSizeInvalidateDelegate);
if (this._parentNode) {
this._parentNode.removeEventListener(ContainerNodeEvent.INVALIDATE_MATRIX3D, this._onInvalidateSceneTransform);
this._parentNode.removeEventListener(ContainerNodeEvent.INVALIDATE_COLOR_TRANSFORM, this._onInvalidateColorTransform);
}
var container = this._asset.container;
if (container)
delete container._renderObjects[this.group.id];
_super.prototype.onClear.call(this);
};
CacheRenderer.registerMaterial = function (renderMaterialClass, materialClass) {
RenderGroup.getInstance(CacheRenderer).registerMaterial(renderMaterialClass, materialClass);
};
CacheRenderer.assetType = '[renderer CacheRenderer]';
return CacheRenderer;
}(RendererBase));
export { CacheRenderer };
var _Render_Renderer = /** @class */ (function (_super) {
__extends(_Render_Renderer, _super);
function _Render_Renderer() {
return _super !== null && _super.apply(this, arguments) || this;
}
_Render_Renderer.prototype._getStageElements = function () {
var asset = this.renderable;
var paddedBounds = asset.getPaddedBounds();
var matrix3D = Matrix3D.CALCULATION_MATRIX;
var scale = asset.getBoundsScale();
matrix3D.copyFrom(this.entity.renderSceneTransform);
matrix3D.appendScale(scale, scale, scale);
matrix3D.invert();
var vectors = [
paddedBounds.left, paddedBounds.top, 0,
paddedBounds.right, paddedBounds.bottom, 0,
paddedBounds.right, paddedBounds.top, 0,
paddedBounds.left, paddedBounds.top, 0,
paddedBounds.left, paddedBounds.bottom, 0,
paddedBounds.right, paddedBounds.bottom, 0,
];
matrix3D.transformVectors(vectors, vectors);
var elements = this._elements;
if (!elements) {
elements = this._elements = new TriangleElements(new AttributesBuffer(5, 6));
elements.setPositions(vectors);
elements.setUVs([0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1]);
}
else {
elements.setPositions(vectors);
}
return this._stage.abstractions.getAbstraction(elements);
};
_Render_Renderer.prototype.draw = function (enableDepthAndStencil, surfaceSelector, mipmapSelector, maskConfig) {
if (enableDepthAndStencil === void 0) { enableDepthAndStencil = true; }
if (surfaceSelector === void 0) { surfaceSelector = 0; }
if (mipmapSelector === void 0) { mipmapSelector = 0; }
if (maskConfig === void 0) { maskConfig = 0; }
// disable cull, because for render to texture it is bugged
this._stage.context.setCulling(ContextGLTriangleFace.NONE);
_super.prototype.draw.call(this);
};
_Render_Renderer.prototype._getRenderMaterial = function () {
return this.entity.renderer
.getRenderElements(this.stageElements.elements).abstractions
.getAbstraction(this.renderable);
};
_Render_Renderer.prototype._getStyle = function () {
return this.renderable.style;
};
_Render_Renderer.assetType = '[render Renderer]';
return _Render_Renderer;
}(_Render_RenderableBase));
export { _Render_Renderer };
DefaultRenderer.registerMaterial(_Render_RendererMaterial, CacheRenderer);
CacheRenderer.registerMaterial(_Render_RendererMaterial, CacheRenderer);
RenderEntity.registerRenderable(_Render_Renderer, CacheRenderer);