123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318 |
- module BABYLON {
- export class Rectangle2DRenderCache extends ModelRenderCache {
- fillVB: WebGLBuffer;
- fillIB: WebGLBuffer;
- fillIndicesCount: number;
- instancingFillAttributes: InstancingAttributeInfo[];
- effectFill: Effect;
- borderVB: WebGLBuffer;
- borderIB: WebGLBuffer;
- borderIndicesCount: number;
- instancingBorderAttributes: InstancingAttributeInfo[];
- effectBorder: Effect;
- constructor(engine: Engine, modelKey: string, isTransparent: boolean) {
- super(engine, modelKey, isTransparent);
- }
- render(instanceInfo: GroupInstanceInfo, context: Render2DContext): boolean {
- // Do nothing if the shader is still loading/preparing
- if ((this.effectFill && !this.effectFill.isReady()) || (this.effectBorder && !this.effectBorder.isReady())) {
- return false;
- }
- var engine = instanceInfo._owner.owner.engine;
- let depthFunction = 0;
- if (this.effectFill && this.effectBorder) {
- depthFunction = engine.getDepthFunction();
- engine.setDepthFunctionToLessOrEqual();
- }
- var cur: number;
- if (this.isTransparent) {
- cur = engine.getAlphaMode();
- engine.setAlphaMode(Engine.ALPHA_COMBINE);
- }
- if (this.effectFill) {
- let partIndex = instanceInfo._partIndexFromId.get(Shape2D.SHAPE2D_FILLPARTID.toString());
- engine.enableEffect(this.effectFill);
- engine.bindBuffers(this.fillVB, this.fillIB, [1], 4, this.effectFill);
- let count = instanceInfo._instancesPartsData[partIndex].usedElementCount;
- if (instanceInfo._owner.owner.supportInstancedArray) {
- if (!this.instancingFillAttributes) {
- // Compute the offset locations of the attributes in the vertex shader that will be mapped to the instance buffer data
- this.instancingFillAttributes = this.loadInstancingAttributes(Shape2D.SHAPE2D_FILLPARTID, this.effectFill);
- }
- engine.updateAndBindInstancesBuffer(instanceInfo._instancesPartsBuffer[partIndex], null, this.instancingFillAttributes);
- engine.draw(true, 0, this.fillIndicesCount, count);
- engine.unBindInstancesBuffer(instanceInfo._instancesPartsBuffer[partIndex], this.instancingFillAttributes);
- } else {
- for (let i = 0; i < count; i++) {
- this.setupUniforms(this.effectFill, partIndex, instanceInfo._instancesPartsData[partIndex], i);
- engine.draw(true, 0, this.fillIndicesCount);
- }
- }
- }
- if (this.effectBorder) {
- let partIndex = instanceInfo._partIndexFromId.get(Shape2D.SHAPE2D_BORDERPARTID.toString());
- engine.enableEffect(this.effectBorder);
- engine.bindBuffers(this.borderVB, this.borderIB, [1], 4, this.effectBorder);
- let count = instanceInfo._instancesPartsData[partIndex].usedElementCount;
- if (instanceInfo._owner.owner.supportInstancedArray) {
- if (!this.instancingBorderAttributes) {
- this.instancingBorderAttributes = this.loadInstancingAttributes(Shape2D.SHAPE2D_BORDERPARTID, this.effectBorder);
- }
- engine.updateAndBindInstancesBuffer(instanceInfo._instancesPartsBuffer[partIndex], null, this.instancingBorderAttributes);
- engine.draw(true, 0, this.borderIndicesCount, count);
- engine.unBindInstancesBuffer(instanceInfo._instancesPartsBuffer[partIndex], this.instancingBorderAttributes);
- } else {
- for (let i = 0; i < count; i++) {
- this.setupUniforms(this.effectBorder, partIndex, instanceInfo._instancesPartsData[partIndex], i);
- engine.draw(true, 0, this.borderIndicesCount);
- }
- }
- }
- if (this.isTransparent) {
- engine.setAlphaMode(cur);
- }
- if (this.effectFill && this.effectBorder) {
- engine.setDepthFunction(depthFunction);
- }
- return true;
- }
- public dispose(): boolean {
- if (!super.dispose()) {
- return false;
- }
- if (this.fillVB) {
- this._engine._releaseBuffer(this.fillVB);
- this.fillVB = null;
- }
- if (this.fillIB) {
- this._engine._releaseBuffer(this.fillIB);
- this.fillIB = null;
- }
- if (this.effectFill) {
- this._engine._releaseEffect(this.effectFill);
- this.effectFill = null;
- }
- if (this.borderVB) {
- this._engine._releaseBuffer(this.borderVB);
- this.borderVB = null;
- }
- if (this.borderIB) {
- this._engine._releaseBuffer(this.borderIB);
- this.borderIB = null;
- }
- if (this.effectBorder) {
- this._engine._releaseEffect(this.effectBorder);
- this.effectBorder = null;
- }
- return true;
- }
- }
- export class Rectangle2DInstanceData extends Shape2DInstanceData {
- constructor(partId: number) {
- super(partId, 1);
- }
- @instanceData()
- get properties(): Vector3 {
- return null;
- }
- }
- @className("Rectangle2D")
- export class Rectangle2D extends Shape2D {
- public static sizeProperty: Prim2DPropInfo;
- public static notRoundedProperty: Prim2DPropInfo;
- public static roundRadiusProperty: Prim2DPropInfo;
- @instanceLevelProperty(Shape2D.SHAPE2D_PROPCOUNT + 1, pi => Rectangle2D.sizeProperty = pi, false, true)
- public get size(): Size {
- return this._size;
- }
- public set size(value: Size) {
- this._size = value;
- }
- @modelLevelProperty(Shape2D.SHAPE2D_PROPCOUNT + 2, pi => Rectangle2D.notRoundedProperty = pi)
- public get notRounded(): boolean {
- return this._notRounded;
- }
- public set notRounded(value: boolean) {
- this._notRounded = value;
- }
- @instanceLevelProperty(Shape2D.SHAPE2D_PROPCOUNT + 3, pi => Rectangle2D.roundRadiusProperty = pi)
- public get roundRadius(): number {
- return this._roundRadius;
- }
- public set roundRadius(value: number) {
- this._roundRadius = value;
- this.notRounded = value === 0;
- }
- protected updateLevelBoundingInfo() {
- BoundingInfo2D.CreateFromSizeToRef(this.size, this._levelBoundingInfo);
- }
- protected setupRectangle2D(owner: Canvas2D, parent: Prim2DBase, id: string, position: Vector2, size: Size, roundRadius = 0, fill?: IBrush2D, border?: IBrush2D, borderThickness: number = 1) {
- this.setupShape2D(owner, parent, id, position, true, fill, border, borderThickness);
- this.size = size;
- this.notRounded = !roundRadius;
- this.roundRadius = roundRadius;
- }
- public static Create(parent: Prim2DBase, id: string, x: number, y: number, width: number, height: number, fill?: IBrush2D, border?: IBrush2D): Rectangle2D {
- Prim2DBase.CheckParent(parent);
- let rect = new Rectangle2D();
- rect.setupRectangle2D(parent.owner, parent, id, new Vector2(x, y), new Size(width, height), null);
- rect.fill = fill;
- rect.border = border;
- return rect;
- }
- public static CreateRounded(parent: Prim2DBase, id: string, x: number, y: number, width: number, height: number, roundRadius = 0, fill?: IBrush2D, border?: IBrush2D): Rectangle2D {
- Prim2DBase.CheckParent(parent);
- let rect = new Rectangle2D();
- rect.setupRectangle2D(parent.owner, parent, id, new Vector2(x, y), new Size(width, height), roundRadius);
- rect.fill = fill || Canvas2D.GetSolidColorBrushFromHex("#FFFFFFFF");
- rect.border = border;
- return rect;
- }
- public static roundSubdivisions = 16;
- protected createModelRenderCache(modelKey: string, isTransparent: boolean): ModelRenderCache {
- let renderCache = new Rectangle2DRenderCache(this.owner.engine, modelKey, isTransparent);
- return renderCache;
- }
- protected setupModelRenderCache(modelRenderCache: ModelRenderCache) {
- let renderCache = <Rectangle2DRenderCache>modelRenderCache;
- let engine = this.owner.engine;
- // Need to create WebGL resources for fill part?
- if (this.fill) {
- let vbSize = ((this.notRounded ? 1 : Rectangle2D.roundSubdivisions) * 4) + 1;
- let vb = new Float32Array(vbSize);
- for (let i = 0; i < vbSize; i++) {
- vb[i] = i;
- }
- renderCache.fillVB = engine.createVertexBuffer(vb);
- let triCount = vbSize - 1;
- let ib = new Float32Array(triCount * 3);
- for (let i = 0; i < triCount; i++) {
- ib[i * 3 + 0] = 0;
- ib[i * 3 + 2] = i + 1;
- ib[i * 3 + 1] = i + 2;
- }
- ib[triCount * 3 - 2] = 1;
- renderCache.fillIB = engine.createIndexBuffer(ib);
- renderCache.fillIndicesCount = triCount * 3;
- let ei = this.getDataPartEffectInfo(Shape2D.SHAPE2D_FILLPARTID, ["index"]);
- renderCache.effectFill = engine.createEffect({ vertex: "rect2d", fragment: "rect2d" }, ei.attributes, ei.uniforms, [], ei.defines, null, e => {
- // renderCache.setupUniformsLocation(e, ei.uniforms, Shape2D.SHAPE2D_FILLPARTID);
- });
- }
- // Need to create WebGL resource for border part?
- if (this.border) {
- let vbSize = (this.notRounded ? 1 : Rectangle2D.roundSubdivisions) * 4 * 2;
- let vb = new Float32Array(vbSize);
- for (let i = 0; i < vbSize; i++) {
- vb[i] = i;
- }
- renderCache.borderVB = engine.createVertexBuffer(vb);
- let triCount = vbSize;
- let rs = triCount / 2;
- let ib = new Float32Array(triCount * 3);
- for (let i = 0; i < rs; i++) {
- let r0 = i;
- let r1 = (i + 1) % rs;
- ib[i * 6 + 0] = rs + r1;
- ib[i * 6 + 1] = rs + r0;
- ib[i * 6 + 2] = r0;
- ib[i * 6 + 3] = r1;
- ib[i * 6 + 4] = rs + r1;
- ib[i * 6 + 5] = r0;
- }
- renderCache.borderIB = engine.createIndexBuffer(ib);
- renderCache.borderIndicesCount = triCount * 3;
- let ei = this.getDataPartEffectInfo(Shape2D.SHAPE2D_BORDERPARTID, ["index"]);
- renderCache.effectBorder = engine.createEffect({ vertex: "rect2d", fragment: "rect2d" }, ei.attributes, ei.uniforms, [], ei.defines, null, e => {
- // renderCache.setupUniformsLocation(e, ei.uniforms, Shape2D.SHAPE2D_BORDERPARTID);
- });
- }
- return renderCache;
- }
- protected createInstanceDataParts(): InstanceDataBase[] {
- var res = new Array<InstanceDataBase>();
- if (this.border) {
- res.push(new Rectangle2DInstanceData(Shape2D.SHAPE2D_BORDERPARTID));
- }
- if (this.fill) {
- res.push(new Rectangle2DInstanceData(Shape2D.SHAPE2D_FILLPARTID));
- }
- return res;
- }
- protected refreshInstanceDataPart(part: InstanceDataBase): boolean {
- if (!super.refreshInstanceDataPart(part)) {
- return false;
- }
- if (part.id === Shape2D.SHAPE2D_BORDERPARTID) {
- let d = <Rectangle2DInstanceData>part;
- let size = this.size;
- d.properties = new Vector3(size.width, size.height, this.roundRadius || 0);
- }
- else if (part.id === Shape2D.SHAPE2D_FILLPARTID) {
- let d = <Rectangle2DInstanceData>part;
- let size = this.size;
- d.properties = new Vector3(size.width, size.height, this.roundRadius || 0);
- }
- return true;
- }
- private _size: Size;
- private _notRounded: boolean;
- private _roundRadius: number;
- }
- }
|