import { ComponentDatatype } from "../../Source/Cesium.js"; import { BufferUsage } from "../../Source/Cesium.js"; import { VertexArrayFacade } from "../../Source/Cesium.js"; import createContext from "../createContext.js"; describe( "Renderer/VertexArrayFacade", function () { var context; beforeAll(function () { context = createContext(); }); afterAll(function () { context.destroyForSpecs(); }); it("creates a vertex array with static floats", function () { var positionIndex = 0; var vaf = new VertexArrayFacade( context, [ { index: positionIndex, componentsPerAttribute: 3, componentDatatype: ComponentDatatype.FLOAT, usage: BufferUsage.STATIC_DRAW, }, ], 1 ); var writer = vaf.writers[positionIndex]; expect(writer).toBeDefined(); writer(0, 1.0, 2.0, 3.0); // Write [1.0, 2.0, 3.0] at index zero. vaf.commit(); // Commit writes expect(vaf.va[0].va.getAttribute(0).vertexBuffer).toBeDefined(); expect(vaf.va[0].va.getAttribute(0).vertexBuffer.sizeInBytes).toEqual( 1 * 3 * 4 ); expect(vaf.va[0].va.getAttribute(0).vertexBuffer.usage).toEqual( BufferUsage.STATIC_DRAW ); expect(vaf.va[0].va.getAttribute(0).componentsPerAttribute).toEqual(3); expect(vaf.va[0].va.getAttribute(0).componentDatatype).toEqual( ComponentDatatype.FLOAT ); expect(vaf.va[0].va.getAttribute(0).offsetInBytes).toEqual(0); expect(vaf.va[0].va.getAttribute(0).strideInBytes).toEqual(3 * 4); }); it("resizes a vertex array with static floats", function () { var positionIndex = 0; var vaf = new VertexArrayFacade( context, [ { index: positionIndex, componentsPerAttribute: 3, componentDatatype: ComponentDatatype.FLOAT, usage: BufferUsage.STATIC_DRAW, }, ], 1 ); var writer = vaf.writers[positionIndex]; expect(writer).toBeDefined(); writer(0, 1.0, 2.0, 3.0); // Write [1.0, 2.0, 3.0] at index zero. vaf.resize(2); // Two vertices writer(1, 1.0, 2.0, 3.0); // Write [4.0, 5.0, 6.0] at index one. vaf.commit(); // Commit writes expect(vaf.va[0].va.getAttribute(0).vertexBuffer).toBeDefined(); expect(vaf.va[0].va.getAttribute(0).vertexBuffer.sizeInBytes).toEqual( 2 * 3 * 4 ); expect(vaf.va[0].va.getAttribute(0).vertexBuffer.usage).toEqual( BufferUsage.STATIC_DRAW ); expect(vaf.va[0].va.getAttribute(0).componentsPerAttribute).toEqual(3); expect(vaf.va[0].va.getAttribute(0).componentDatatype).toEqual( ComponentDatatype.FLOAT ); expect(vaf.va[0].va.getAttribute(0).offsetInBytes).toEqual(0); expect(vaf.va[0].va.getAttribute(0).strideInBytes).toEqual(3 * 4); }); it("creates a vertex array with static floats and unsigned bytes", function () { var positionIndex = 0; var colorIndex = 2; var vaf = new VertexArrayFacade( context, [ { index: positionIndex, componentsPerAttribute: 3, componentDatatype: ComponentDatatype.FLOAT, usage: BufferUsage.STATIC_DRAW, }, { index: colorIndex, componentsPerAttribute: 4, componentDatatype: ComponentDatatype.UNSIGNED_BYTE, usage: BufferUsage.STATIC_DRAW, }, ], 1 ); var positionWriter = vaf.writers[positionIndex]; var colorWriter = vaf.writers[colorIndex]; expect(positionWriter).toBeDefined(); expect(colorWriter).toBeDefined(); positionWriter(0, 1.0, 2.0, 3.0); // Write position [1.0, 2.0, 3.0] at index zero. colorWriter(0, 0, 255, 0, 255); // Write color [0, 255, 0, 255] at index zero. vaf.commit(); // Commit writes // Position attribute expect(vaf.va[0].va.getAttribute(0).vertexBuffer).toBeDefined(); expect(vaf.va[0].va.getAttribute(0).vertexBuffer.sizeInBytes).toEqual( 1 * (3 * 4 + 4 * 1) ); expect(vaf.va[0].va.getAttribute(0).vertexBuffer.usage).toEqual( BufferUsage.STATIC_DRAW ); expect(vaf.va[0].va.getAttribute(0).componentsPerAttribute).toEqual(3); expect(vaf.va[0].va.getAttribute(0).componentDatatype).toEqual( ComponentDatatype.FLOAT ); expect(vaf.va[0].va.getAttribute(0).offsetInBytes).toEqual(0); expect(vaf.va[0].va.getAttribute(0).strideInBytes).toEqual(3 * 4 + 4 * 1); // Color attribute expect(vaf.va[0].va.getAttribute(1).vertexBuffer).toEqual( vaf.va[0].va.getAttribute(0).vertexBuffer ); expect(vaf.va[0].va.getAttribute(1).componentsPerAttribute).toEqual(4); expect(vaf.va[0].va.getAttribute(1).componentDatatype).toEqual( ComponentDatatype.UNSIGNED_BYTE ); expect(vaf.va[0].va.getAttribute(1).offsetInBytes).toEqual(3 * 4); expect(vaf.va[0].va.getAttribute(1).strideInBytes).toEqual( vaf.va[0].va.getAttribute(0).strideInBytes ); }); it("creates a vertex array with static and dynamic attributes", function () { var positionIndex = 0; var txCoordIndex = 2; var vaf = new VertexArrayFacade( context, [ { index: positionIndex, componentsPerAttribute: 3, componentDatatype: ComponentDatatype.FLOAT, usage: BufferUsage.STATIC_DRAW, }, { index: txCoordIndex, componentsPerAttribute: 2, componentDatatype: ComponentDatatype.UNSIGNED_SHORT, usage: BufferUsage.DYNAMIC_DRAW, normalize: true, }, ], 1 ); var positionWriter = vaf.writers[positionIndex]; var txCoordWriter = vaf.writers[txCoordIndex]; expect(positionWriter).toBeDefined(); expect(txCoordWriter).toBeDefined(); positionWriter(0, 1.0, 2.0, 3.0); txCoordWriter(0, 32 * 1024, 64 * 1024); vaf.commit(); // Position attribute expect(vaf.va[0].va.getAttribute(0).vertexBuffer).toBeDefined(); expect(vaf.va[0].va.getAttribute(0).vertexBuffer.sizeInBytes).toEqual( 1 * (3 * 4) ); expect(vaf.va[0].va.getAttribute(0).vertexBuffer.usage).toEqual( BufferUsage.STATIC_DRAW ); expect(vaf.va[0].va.getAttribute(0).componentsPerAttribute).toEqual(3); expect(vaf.va[0].va.getAttribute(0).componentDatatype).toEqual( ComponentDatatype.FLOAT ); expect(vaf.va[0].va.getAttribute(0).offsetInBytes).toEqual(0); expect(vaf.va[0].va.getAttribute(0).strideInBytes).toEqual(3 * 4); // Texture coordinate attribute expect(vaf.va[0].va.getAttribute(1).vertexBuffer).toBeDefined(); expect(vaf.va[0].va.getAttribute(1).vertexBuffer.sizeInBytes).toEqual( 1 * (2 * 2) ); expect(vaf.va[0].va.getAttribute(1).vertexBuffer.usage).toEqual( BufferUsage.DYNAMIC_DRAW ); expect(vaf.va[0].va.getAttribute(1).componentsPerAttribute).toEqual(2); expect(vaf.va[0].va.getAttribute(1).componentDatatype).toEqual( ComponentDatatype.UNSIGNED_SHORT ); expect(vaf.va[0].va.getAttribute(1).offsetInBytes).toEqual(0); expect(vaf.va[0].va.getAttribute(1).strideInBytes).toEqual(2 * 2); }); it("sub-commits", function () { var positionIndex = 0; var temperatureIndex = 2; var vaf = new VertexArrayFacade( context, [ { index: positionIndex, componentsPerAttribute: 3, componentDatatype: ComponentDatatype.FLOAT, usage: BufferUsage.STATIC_DRAW, }, { index: temperatureIndex, componentsPerAttribute: 1, componentDatatype: ComponentDatatype.FLOAT, usage: BufferUsage.STREAM_DRAW, }, ], 2 ); var positionWriter = vaf.writers[positionIndex]; var temperatureWriter = vaf.writers[temperatureIndex]; expect(positionWriter).toBeDefined(); expect(temperatureWriter).toBeDefined(); positionWriter(0, 1.0, 2.0, 3.0); temperatureWriter(0, 98.6); positionWriter(1, 7.0, 8.0, 9.0); temperatureWriter(1, 32.0); vaf.commit(); // Rewrite all vertices positionWriter(0, 10.0, 20.0, 30.0); temperatureWriter(0, 37.0); positionWriter(1, 70.0, 80.0, 90.0); temperatureWriter(1, 0.0); vaf.commit(); // Sub-commit to just one vertex temperatureWriter(1, 212.0); vaf.subCommit(1, 1); vaf.endSubCommits(); // Position attribute expect(vaf.va[0].va.getAttribute(1).vertexBuffer).toBeDefined(); expect(vaf.va[0].va.getAttribute(1).vertexBuffer.sizeInBytes).toEqual( 2 * (3 * 4) ); expect(vaf.va[0].va.getAttribute(1).vertexBuffer.usage).toEqual( BufferUsage.STATIC_DRAW ); expect(vaf.va[0].va.getAttribute(1).componentsPerAttribute).toEqual(3); expect(vaf.va[0].va.getAttribute(1).componentDatatype).toEqual( ComponentDatatype.FLOAT ); expect(vaf.va[0].va.getAttribute(1).offsetInBytes).toEqual(0); expect(vaf.va[0].va.getAttribute(1).strideInBytes).toEqual(3 * 4); // Temperature attribute expect(vaf.va[0].va.getAttribute(0).vertexBuffer).toBeDefined(); expect(vaf.va[0].va.getAttribute(0).vertexBuffer.sizeInBytes).toEqual( 2 * 4 ); expect(vaf.va[0].va.getAttribute(0).vertexBuffer.usage).toEqual( BufferUsage.STREAM_DRAW ); expect(vaf.va[0].va.getAttribute(0).componentsPerAttribute).toEqual(1); expect(vaf.va[0].va.getAttribute(0).componentDatatype).toEqual( ComponentDatatype.FLOAT ); expect(vaf.va[0].va.getAttribute(0).offsetInBytes).toEqual(0); expect(vaf.va[0].va.getAttribute(0).strideInBytes).toEqual(1 * 4); }); it("destroys previous vertex buffers when number of vertices grows", function () { var positionIndex = 0; var vaf = new VertexArrayFacade( context, [ { index: positionIndex, componentsPerAttribute: 3, componentDatatype: ComponentDatatype.FLOAT, usage: BufferUsage.STATIC_DRAW, }, ], 1 ); var writer = vaf.writers[positionIndex]; expect(writer).toBeDefined(); writer(0, 1.0, 2.0, 3.0); // Write [1.0, 2.0, 3.0] at index zero. vaf.commit(); // Commit writes // Grab the vertex buffer var vbBeforeResize = vaf.va[0].va.getAttribute(0).vertexBuffer; vaf.resize(2); // Two vertices writer(1, 1.0, 2.0, 3.0); // Write [4.0, 5.0, 6.0] at index one. vaf.commit(); // Commit writes expect(vbBeforeResize.isDestroyed()).toBe(true); expect(vaf.va[0].va.getAttribute(0).vertexBuffer).not.toBe( vbBeforeResize ); }); it("is not initially destroyed", function () { var positionIndex = 0; var vaf = new VertexArrayFacade( context, [ { index: positionIndex, componentsPerAttribute: 3, componentDatatype: ComponentDatatype.FLOAT, usage: BufferUsage.STATIC_DRAW, }, ], 1 ); expect(vaf.isDestroyed()).toBe(false); }); it("throws when constructed without a context", function () { expect(function () { return new VertexArrayFacade(undefined, undefined, undefined); }).toThrowDeveloperError(); }); it("throws when constructed undefined attributes", function () { expect(function () { return new VertexArrayFacade(context, undefined, undefined); }).toThrowDeveloperError(); }); it("throws when constructed without attributes", function () { expect(function () { return new VertexArrayFacade(context, []); }).toThrowDeveloperError(); }); it("throws when constructed with attributes without componentsPerAttribute", function () { expect(function () { return new VertexArrayFacade(context, [{}]); }).toThrowDeveloperError(); }); it("throws when constructed with attributes with an invalid componentDatatype", function () { expect(function () { return new VertexArrayFacade(context, [ { componentsPerAttribute: 1, componentDatatype: "invalid component datatype", }, ]); }).toThrowDeveloperError(); }); it("throws when constructed with attributes with an invalid usage", function () { expect(function () { return new VertexArrayFacade(context, [ { componentsPerAttribute: 1, usage: "invalid component usage", }, ]); }).toThrowDeveloperError(); }); it("throws when constructed with attributes with duplicate indices", function () { expect(function () { return new VertexArrayFacade(context, [ { index: 0, componentsPerAttribute: 1, }, { index: 0, componentsPerAttribute: 1, }, ]); }).toThrowDeveloperError(); }); it("subCommit throws when passed an invalid offsetInVertices", function () { var positionIndex = 0; var vaf = new VertexArrayFacade( context, [ { index: positionIndex, componentsPerAttribute: 3, componentDatatype: ComponentDatatype.FLOAT, usage: BufferUsage.STATIC_DRAW, }, ], 10 ); expect(function () { vaf.subCommit(-1, 1); }).toThrowDeveloperError(); expect(function () { vaf.subCommit(10, 1); }).toThrowDeveloperError(); expect(function () { vaf.subCommit(1, 10); }).toThrowDeveloperError(); }); }, "WebGL" );