UNPKG

@awayjs/renderer

Version:
290 lines (223 loc) 6.19 kB
import { AbstractMethodError, Matrix, AbstractionBase, } from '@awayjs/core'; import { Stage, _Stage_ImageBase, ImageSampler, } from '@awayjs/stage'; import { MaterialUtils } from '../utils/MaterialUtils'; import { _Render_MaterialBase } from './_Render_MaterialBase'; import { _Stage_ElementsBase } from './_Stage_ElementsBase'; import { IPass } from './IPass'; import { IMaterial } from './IMaterial'; import { RenderEntity } from './RenderEntity'; import { ITexture } from './ITexture'; import { Style } from './Style'; import { IShaderBase } from './IShaderBase'; import { IRenderable } from './IRenderable'; /** * @class RenderableListItem */ export class _Render_RenderableBase extends AbstractionBase { private _renderMaterial: _Render_MaterialBase; private _materialDirty: boolean = true; private _stageElements: _Stage_ElementsBase; private _elementsDirty: boolean = true; private _styleDirty: boolean = true; private _images: _Stage_ImageBase[] = []; private _samplers: ImageSampler[] = []; private _uvMatrix: Matrix; public JOINT_INDEX_FORMAT: string; public JOINT_WEIGHT_FORMAT: string; public _count: number = 0; public _offset: number = 0; protected _stage: Stage; /** * */ public get images(): Array<_Stage_ImageBase> { if (this._styleDirty) this._updateStyle(); return this._images; } /** * */ public get samplers(): Array<ImageSampler> { if (this._styleDirty) this._updateStyle(); return this._samplers; } /** * */ public get uvMatrix(): Matrix { if (this._styleDirty) this._updateStyle(); return this._uvMatrix; } /** * */ public next: _Render_RenderableBase; /** * */ public materialID: number; /** * */ public renderOrderId: number; /** * */ public cascaded: boolean; /** * * @returns {_Stage_ElementsBase} */ public get stageElements(): _Stage_ElementsBase { if (this._elementsDirty) this._updateElements(); return this._stageElements; } /** * * @returns {_Render_MaterialBase} */ public get renderMaterial(): _Render_MaterialBase { if (this._materialDirty) this._updateMaterial(); return this._renderMaterial; } public get entity(): RenderEntity { return <RenderEntity> this._pool; } public get renderable(): IRenderable { return this._useWeak ? (<WeakRef<IRenderable>> this._asset).deref() : <IRenderable> this._asset; } constructor() { super(); } /** * * @param renderable * @param sourceEntity * @param surface * @param renderer */ public init(renderable: IRenderable, entity: RenderEntity): void { super.init(renderable, entity, true); //store references this._stage = entity.renderer.stage; renderable._renderObjects[entity.id] = this; } /** * Renders an object to the current render target. * * @private */ public draw(): void { const pass: IPass = this._renderMaterial._activePass; pass._setRenderState(this); const shader: IShaderBase = pass.shader; const elements: _Stage_ElementsBase = this.stageElements; if (shader.activeElements != elements) { shader.activeElements = elements; elements._setRenderState(this, shader); } elements.draw(this, shader, this._count, this._offset); } public onClear(): void { const renderable: IRenderable = this.renderable; if (renderable) delete renderable._renderObjects[(<RenderEntity> this._pool).id]; this._stage = null; this.next = null; this._renderMaterial.removeOwner(this); this._renderMaterial = null; this._stageElements = null; this._materialDirty = true; this._elementsDirty = true; this._styleDirty = true; this._images.length = 0; this._samplers.length = 0; this._uvMatrix = null; super.onClear(); } public _onInvalidateElements(): void { this._elementsDirty = true; } public _onInvalidateMaterial(): void { this._materialDirty = true; this._styleDirty = true; } public _onInvalidateStyle(): void { this._styleDirty = true; } protected _getStageElements(): _Stage_ElementsBase { throw new AbstractMethodError(); } protected _getRenderMaterial(): _Render_MaterialBase { throw new AbstractMethodError(); } protected _getStyle(): Style { throw new AbstractMethodError(); } /** * //TODO * * @private */ private _updateElements(): void { this._stageElements = this._getStageElements(); this._elementsDirty = false; } protected _updateMaterial(): void { const renderMaterial: _Render_MaterialBase = this._getRenderMaterial(); if (this._renderMaterial != renderMaterial) { if (this._renderMaterial) this._renderMaterial.removeOwner(this); this._renderMaterial = renderMaterial; this._renderMaterial.addOwner(this); } this._materialDirty = false; } protected _updateStyle(): void { const style: Style = this._getStyle(); if (this._materialDirty) this._updateMaterial(); //create a cache of image & sampler objects for the renderable let numImages: number = this._renderMaterial.numImages; const material: IMaterial = this._renderMaterial.material; this._images.length = numImages; this._samplers.length = numImages; const uvMatrix = style ? style.uvMatrix : material.style ? material.style.uvMatrix : null; if (uvMatrix) this._uvMatrix = this.stageElements.transformMatrix(this, uvMatrix); const numTextures: number = this._renderMaterial.material.getNumTextures(); let texture: ITexture; let index: number; for (let i: number = 0; i < numTextures; i++) { texture = material.getTextureAt(i); numImages = texture.getNumImages(); for (let j: number = 0; j < numImages; j++) { index = this._renderMaterial.getImageIndex(texture, j); this._images[index] = this._stage.abstractions .getAbstraction<_Stage_ImageBase>( style?.getImageAt(texture, j) || this._renderMaterial.images[index] ); this._samplers[index] = style?.getSamplerAt(texture, j) || this._renderMaterial.samplers[index]; } } this._styleDirty = false; } protected getDefaultMaterial(): IMaterial { return MaterialUtils.getDefaultTextureMaterial(); } }