678 lines
25 KiB
JavaScript
678 lines
25 KiB
JavaScript
|
|
defineSuite([
|
||
|
|
'Core/ComponentDatatype',
|
||
|
|
'Core/Geometry',
|
||
|
|
'Core/GeometryAttribute',
|
||
|
|
'Core/GeometryPipeline',
|
||
|
|
'Core/IndexDatatype',
|
||
|
|
'Core/PrimitiveType',
|
||
|
|
'Renderer/BufferUsage',
|
||
|
|
'Renderer/ClearCommand',
|
||
|
|
'Renderer/DrawCommand',
|
||
|
|
'Renderer/ShaderProgram',
|
||
|
|
'Renderer/VertexArray',
|
||
|
|
'Specs/createContext'
|
||
|
|
], 'Renderer/VertexArrayFactory', function(
|
||
|
|
ComponentDatatype,
|
||
|
|
Geometry,
|
||
|
|
GeometryAttribute,
|
||
|
|
GeometryPipeline,
|
||
|
|
IndexDatatype,
|
||
|
|
PrimitiveType,
|
||
|
|
BufferUsage,
|
||
|
|
ClearCommand,
|
||
|
|
DrawCommand,
|
||
|
|
ShaderProgram,
|
||
|
|
VertexArray,
|
||
|
|
createContext) {
|
||
|
|
'use strict';
|
||
|
|
|
||
|
|
var context;
|
||
|
|
var va;
|
||
|
|
var sp;
|
||
|
|
|
||
|
|
beforeAll(function() {
|
||
|
|
context = createContext();
|
||
|
|
});
|
||
|
|
|
||
|
|
afterAll(function() {
|
||
|
|
context.destroyForSpecs();
|
||
|
|
});
|
||
|
|
|
||
|
|
afterEach(function() {
|
||
|
|
va = va && va.destroy();
|
||
|
|
sp = sp && sp.destroy();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('throws when there is no context', function() {
|
||
|
|
expect(function() {
|
||
|
|
return VertexArray.fromGeometry();
|
||
|
|
}).toThrowDeveloperError();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('creates with no optional arguments', function() {
|
||
|
|
va = VertexArray.fromGeometry({
|
||
|
|
context : context
|
||
|
|
});
|
||
|
|
expect(va.numberOfAttributes).toEqual(0);
|
||
|
|
expect(va.indexBuffer).not.toBeDefined();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('creates with no geometry', function() {
|
||
|
|
va = VertexArray.fromGeometry({
|
||
|
|
context : context,
|
||
|
|
interleave : true
|
||
|
|
});
|
||
|
|
expect(va.numberOfAttributes).toEqual(0);
|
||
|
|
expect(va.indexBuffer).not.toBeDefined();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('creates a single-attribute vertex (non-interleaved)', function() {
|
||
|
|
var geometry = new Geometry({
|
||
|
|
attributes : {
|
||
|
|
position : new GeometryAttribute({
|
||
|
|
componentDatatype : ComponentDatatype.FLOAT,
|
||
|
|
componentsPerAttribute : 3,
|
||
|
|
values : [0.0, 0.0, 0.0, 1.0, 1.0, 1.0]
|
||
|
|
})
|
||
|
|
},
|
||
|
|
primitiveType : PrimitiveType.POINTS
|
||
|
|
});
|
||
|
|
|
||
|
|
var va = VertexArray.fromGeometry({
|
||
|
|
context : context,
|
||
|
|
geometry : geometry,
|
||
|
|
attributeLocations : GeometryPipeline.createAttributeLocations(geometry)
|
||
|
|
});
|
||
|
|
|
||
|
|
expect(va.numberOfAttributes).toEqual(1);
|
||
|
|
expect(va.indexBuffer).not.toBeDefined();
|
||
|
|
|
||
|
|
var position = geometry.attributes.position;
|
||
|
|
expect(va.getAttribute(0).index).toEqual(0);
|
||
|
|
expect(va.getAttribute(0).componentDatatype).toEqual(position.componentDatatype);
|
||
|
|
expect(va.getAttribute(0).componentsPerAttribute).toEqual(position.componentsPerAttribute);
|
||
|
|
expect(va.getAttribute(0).offsetInBytes).toEqual(0);
|
||
|
|
expect(va.getAttribute(0).strideInBytes).toEqual(0); // Tightly packed
|
||
|
|
|
||
|
|
expect(va.getAttribute(0).vertexBuffer.usage).toEqual(BufferUsage.DYNAMIC_DRAW); // Default
|
||
|
|
});
|
||
|
|
|
||
|
|
it('creates a single-attribute vertex (interleaved)', function() {
|
||
|
|
var geometry = new Geometry({
|
||
|
|
attributes : {
|
||
|
|
position : new GeometryAttribute({
|
||
|
|
componentDatatype : ComponentDatatype.FLOAT,
|
||
|
|
componentsPerAttribute : 3,
|
||
|
|
values : [0.0, 0.0, 0.0, 1.0, 1.0, 1.0]
|
||
|
|
})
|
||
|
|
},
|
||
|
|
primitiveType : PrimitiveType.POINTS
|
||
|
|
});
|
||
|
|
|
||
|
|
var va = VertexArray.fromGeometry({
|
||
|
|
context : context,
|
||
|
|
geometry : geometry,
|
||
|
|
attributeLocations : GeometryPipeline.createAttributeLocations(geometry),
|
||
|
|
interleave : true,
|
||
|
|
bufferUsage : BufferUsage.STATIC_DRAW
|
||
|
|
});
|
||
|
|
|
||
|
|
expect(va.numberOfAttributes).toEqual(1);
|
||
|
|
expect(va.indexBuffer).not.toBeDefined();
|
||
|
|
|
||
|
|
var position = geometry.attributes.position;
|
||
|
|
expect(va.getAttribute(0).index).toEqual(0);
|
||
|
|
expect(va.getAttribute(0).componentDatatype).toEqual(position.componentDatatype);
|
||
|
|
expect(va.getAttribute(0).componentsPerAttribute).toEqual(position.componentsPerAttribute);
|
||
|
|
expect(va.getAttribute(0).offsetInBytes).toEqual(0);
|
||
|
|
expect(va.getAttribute(0).strideInBytes).toEqual(ComponentDatatype.getSizeInBytes(position.componentDatatype) * position.componentsPerAttribute);
|
||
|
|
|
||
|
|
expect(va.getAttribute(0).vertexBuffer.usage).toEqual(BufferUsage.STATIC_DRAW);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('creates a homogeneous multiple-attribute vertex (non-interleaved)', function() {
|
||
|
|
var geometry = new Geometry({
|
||
|
|
attributes : {
|
||
|
|
customPosition : new GeometryAttribute({
|
||
|
|
componentDatatype : ComponentDatatype.FLOAT,
|
||
|
|
componentsPerAttribute : 3,
|
||
|
|
values : [0.0, 0.0, 0.0, 2.0, 2.0, 2.0]
|
||
|
|
}),
|
||
|
|
customNormal : new GeometryAttribute({
|
||
|
|
componentDatatype : ComponentDatatype.FLOAT,
|
||
|
|
componentsPerAttribute : 3,
|
||
|
|
values : [1.0, 1.0, 1.0, 3.0, 3.0, 3.0]
|
||
|
|
})
|
||
|
|
},
|
||
|
|
primitiveType : PrimitiveType.POINTS
|
||
|
|
});
|
||
|
|
|
||
|
|
var va = VertexArray.fromGeometry({
|
||
|
|
context : context,
|
||
|
|
geometry : geometry,
|
||
|
|
attributeLocations : GeometryPipeline.createAttributeLocations(geometry)
|
||
|
|
});
|
||
|
|
|
||
|
|
expect(va.numberOfAttributes).toEqual(2);
|
||
|
|
expect(va.indexBuffer).not.toBeDefined();
|
||
|
|
|
||
|
|
var position = geometry.attributes.customPosition;
|
||
|
|
expect(va.getAttribute(0).index).toEqual(0);
|
||
|
|
expect(va.getAttribute(0).componentDatatype).toEqual(position.componentDatatype);
|
||
|
|
expect(va.getAttribute(0).componentsPerAttribute).toEqual(position.componentsPerAttribute);
|
||
|
|
expect(va.getAttribute(0).offsetInBytes).toEqual(0);
|
||
|
|
expect(va.getAttribute(0).strideInBytes).toEqual(0); // Tightly packed
|
||
|
|
|
||
|
|
var normal = geometry.attributes.customNormal;
|
||
|
|
expect(va.getAttribute(1).index).toEqual(1);
|
||
|
|
expect(va.getAttribute(1).componentDatatype).toEqual(normal.componentDatatype);
|
||
|
|
expect(va.getAttribute(1).componentsPerAttribute).toEqual(normal.componentsPerAttribute);
|
||
|
|
expect(va.getAttribute(1).offsetInBytes).toEqual(0);
|
||
|
|
expect(va.getAttribute(1).strideInBytes).toEqual(0); // Tightly packed
|
||
|
|
|
||
|
|
expect(va.getAttribute(0).vertexBuffer).not.toBe(va.getAttribute(1).vertexBuffer);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('creates a homogeneous multiple-attribute vertex (interleaved)', function() {
|
||
|
|
var geometry = new Geometry({
|
||
|
|
attributes : {
|
||
|
|
customPosition : new GeometryAttribute({
|
||
|
|
componentDatatype : ComponentDatatype.FLOAT,
|
||
|
|
componentsPerAttribute : 3,
|
||
|
|
values : [0.0, 0.0, 0.0, 2.0, 2.0, 2.0]
|
||
|
|
}),
|
||
|
|
customNormal : new GeometryAttribute({
|
||
|
|
componentDatatype : ComponentDatatype.FLOAT,
|
||
|
|
componentsPerAttribute : 3,
|
||
|
|
values : [1.0, 1.0, 1.0, 3.0, 3.0, 3.0]
|
||
|
|
})
|
||
|
|
},
|
||
|
|
primitiveType : PrimitiveType.POINTS
|
||
|
|
});
|
||
|
|
|
||
|
|
var va = VertexArray.fromGeometry({
|
||
|
|
context : context,
|
||
|
|
geometry : geometry,
|
||
|
|
attributeLocations : GeometryPipeline.createAttributeLocations(geometry),
|
||
|
|
interleave : true
|
||
|
|
});
|
||
|
|
|
||
|
|
expect(va.numberOfAttributes).toEqual(2);
|
||
|
|
expect(va.indexBuffer).not.toBeDefined();
|
||
|
|
|
||
|
|
var position = geometry.attributes.customPosition;
|
||
|
|
var normal = geometry.attributes.customNormal;
|
||
|
|
var expectedStride = ComponentDatatype.getSizeInBytes(position.componentDatatype) * position.componentsPerAttribute + ComponentDatatype.getSizeInBytes(normal.componentDatatype) * normal.componentsPerAttribute;
|
||
|
|
|
||
|
|
expect(va.getAttribute(0).index).toEqual(0);
|
||
|
|
expect(va.getAttribute(0).componentDatatype).toEqual(position.componentDatatype);
|
||
|
|
expect(va.getAttribute(0).componentsPerAttribute).toEqual(position.componentsPerAttribute);
|
||
|
|
expect(va.getAttribute(0).offsetInBytes).toEqual(0);
|
||
|
|
expect(va.getAttribute(0).strideInBytes).toEqual(expectedStride);
|
||
|
|
|
||
|
|
expect(va.getAttribute(1).index).toEqual(1);
|
||
|
|
expect(va.getAttribute(1).componentDatatype).toEqual(normal.componentDatatype);
|
||
|
|
expect(va.getAttribute(1).componentsPerAttribute).toEqual(normal.componentsPerAttribute);
|
||
|
|
expect(va.getAttribute(1).offsetInBytes).toEqual(ComponentDatatype.getSizeInBytes(position.componentDatatype) * position.componentsPerAttribute);
|
||
|
|
expect(va.getAttribute(1).strideInBytes).toEqual(expectedStride);
|
||
|
|
|
||
|
|
expect(va.getAttribute(0).vertexBuffer).toBe(va.getAttribute(1).vertexBuffer);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('creates a heterogeneous multiple-attribute vertex (interleaved)', function() {
|
||
|
|
var geometry = new Geometry({
|
||
|
|
attributes : {
|
||
|
|
position : new GeometryAttribute({
|
||
|
|
componentDatatype : ComponentDatatype.FLOAT,
|
||
|
|
componentsPerAttribute : 3,
|
||
|
|
values : [0.0, 0.0, 0.0, 2.0, 2.0, 2.0]
|
||
|
|
}),
|
||
|
|
colors : new GeometryAttribute({
|
||
|
|
componentDatatype : ComponentDatatype.UNSIGNED_BYTE,
|
||
|
|
componentsPerAttribute : 4,
|
||
|
|
values : [1, 1, 1, 1, 2, 2, 2, 2]
|
||
|
|
})
|
||
|
|
},
|
||
|
|
primitiveType : PrimitiveType.POINTS
|
||
|
|
});
|
||
|
|
|
||
|
|
var va = VertexArray.fromGeometry({
|
||
|
|
context : context,
|
||
|
|
geometry : geometry,
|
||
|
|
attributeLocations : GeometryPipeline.createAttributeLocations(geometry),
|
||
|
|
interleave : true
|
||
|
|
});
|
||
|
|
|
||
|
|
expect(va.numberOfAttributes).toEqual(2);
|
||
|
|
expect(va.indexBuffer).not.toBeDefined();
|
||
|
|
|
||
|
|
var position = geometry.attributes.position;
|
||
|
|
var colors = geometry.attributes.colors;
|
||
|
|
var expectedStride = ComponentDatatype.getSizeInBytes(position.componentDatatype) * position.componentsPerAttribute + ComponentDatatype.getSizeInBytes(colors.componentDatatype) * colors.componentsPerAttribute;
|
||
|
|
|
||
|
|
expect(va.getAttribute(0).index).toEqual(0);
|
||
|
|
expect(va.getAttribute(0).componentDatatype).toEqual(position.componentDatatype);
|
||
|
|
expect(va.getAttribute(0).componentsPerAttribute).toEqual(position.componentsPerAttribute);
|
||
|
|
expect(va.getAttribute(0).offsetInBytes).toEqual(0);
|
||
|
|
expect(va.getAttribute(0).strideInBytes).toEqual(expectedStride);
|
||
|
|
|
||
|
|
expect(va.getAttribute(1).index).toEqual(1);
|
||
|
|
expect(va.getAttribute(1).componentDatatype).toEqual(colors.componentDatatype);
|
||
|
|
expect(va.getAttribute(1).componentsPerAttribute).toEqual(colors.componentsPerAttribute);
|
||
|
|
expect(va.getAttribute(1).offsetInBytes).toEqual(ComponentDatatype.getSizeInBytes(position.componentDatatype) * position.componentsPerAttribute);
|
||
|
|
expect(va.getAttribute(1).strideInBytes).toEqual(expectedStride);
|
||
|
|
|
||
|
|
expect(va.getAttribute(0).vertexBuffer).toBe(va.getAttribute(1).vertexBuffer);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('sorts interleaved attributes from large to small components', function() {
|
||
|
|
var geometry = new Geometry({
|
||
|
|
attributes : {
|
||
|
|
bytes : new GeometryAttribute({
|
||
|
|
componentDatatype : ComponentDatatype.BYTE,
|
||
|
|
componentsPerAttribute : 1,
|
||
|
|
values : [0]
|
||
|
|
}),
|
||
|
|
shorts : new GeometryAttribute({
|
||
|
|
componentDatatype : ComponentDatatype.SHORT,
|
||
|
|
componentsPerAttribute : 1,
|
||
|
|
values : [1]
|
||
|
|
}),
|
||
|
|
floats : new GeometryAttribute({
|
||
|
|
componentDatatype : ComponentDatatype.FLOAT,
|
||
|
|
componentsPerAttribute : 1,
|
||
|
|
values : [2]
|
||
|
|
})
|
||
|
|
},
|
||
|
|
primitiveType : PrimitiveType.POINTS
|
||
|
|
});
|
||
|
|
|
||
|
|
var attributeLocations = GeometryPipeline.createAttributeLocations(geometry);
|
||
|
|
var va = VertexArray.fromGeometry({
|
||
|
|
context : context,
|
||
|
|
geometry : geometry,
|
||
|
|
attributeLocations : attributeLocations,
|
||
|
|
interleave : true
|
||
|
|
});
|
||
|
|
|
||
|
|
expect(va.numberOfAttributes).toEqual(3);
|
||
|
|
|
||
|
|
var vertexBuffer = va.getAttribute(0).vertexBuffer;
|
||
|
|
expect(vertexBuffer).toBe(va.getAttribute(1).vertexBuffer);
|
||
|
|
expect(vertexBuffer).toBe(va.getAttribute(2).vertexBuffer);
|
||
|
|
expect(vertexBuffer.sizeInBytes).toEqual(8); // Includes 1 byte per-vertex padding
|
||
|
|
|
||
|
|
// Validate via rendering
|
||
|
|
var vs =
|
||
|
|
'attribute float bytes; ' +
|
||
|
|
'attribute float shorts; ' +
|
||
|
|
'attribute float floats; ' +
|
||
|
|
'varying vec4 fsColor; ' +
|
||
|
|
'void main() { ' +
|
||
|
|
' gl_PointSize = 1.0; ' +
|
||
|
|
' gl_Position = vec4(0.0, 0.0, 0.0, 1.0); ' +
|
||
|
|
' fsColor = vec4((bytes == 0.0) && (shorts == 1.0) && (floats == 2.0)); ' +
|
||
|
|
'}';
|
||
|
|
var fs =
|
||
|
|
'varying vec4 fsColor; ' +
|
||
|
|
'void main() { ' +
|
||
|
|
' gl_FragColor = fsColor; ' +
|
||
|
|
'}';
|
||
|
|
|
||
|
|
sp = ShaderProgram.fromCache({
|
||
|
|
context : context,
|
||
|
|
vertexShaderSource : vs,
|
||
|
|
fragmentShaderSource : fs,
|
||
|
|
attributeLocations : attributeLocations
|
||
|
|
});
|
||
|
|
|
||
|
|
ClearCommand.ALL.execute(context);
|
||
|
|
expect(context).toReadPixels([0, 0, 0, 255]);
|
||
|
|
|
||
|
|
var command = new DrawCommand({
|
||
|
|
primitiveType : PrimitiveType.POINTS,
|
||
|
|
shaderProgram : sp,
|
||
|
|
vertexArray : va
|
||
|
|
});
|
||
|
|
command.execute(context);
|
||
|
|
expect(context).toReadPixels([255, 255, 255, 255]);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('sorts interleaved attributes from large to small components (2)', function() {
|
||
|
|
var geometry = new Geometry({
|
||
|
|
attributes : {
|
||
|
|
color : new GeometryAttribute({
|
||
|
|
componentDatatype : ComponentDatatype.UNSIGNED_BYTE,
|
||
|
|
componentsPerAttribute : 4,
|
||
|
|
normalize : true,
|
||
|
|
values : [255, 0, 0, 255, 0, 255, 0, 255]
|
||
|
|
}),
|
||
|
|
position : new GeometryAttribute({
|
||
|
|
componentDatatype : ComponentDatatype.FLOAT,
|
||
|
|
componentsPerAttribute : 3,
|
||
|
|
values : [0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
|
||
|
|
})
|
||
|
|
},
|
||
|
|
primitiveType : PrimitiveType.POINTS
|
||
|
|
});
|
||
|
|
|
||
|
|
var attributeLocations = GeometryPipeline.createAttributeLocations(geometry);
|
||
|
|
var va = VertexArray.fromGeometry({
|
||
|
|
context : context,
|
||
|
|
geometry : geometry,
|
||
|
|
attributeLocations : attributeLocations,
|
||
|
|
interleave : true
|
||
|
|
});
|
||
|
|
|
||
|
|
expect(va.getAttribute(0).vertexBuffer.sizeInBytes).toEqual(32); // No per-vertex padding needed
|
||
|
|
|
||
|
|
// Validate via rendering
|
||
|
|
var vs =
|
||
|
|
'attribute vec3 position; ' +
|
||
|
|
'attribute vec4 color; ' +
|
||
|
|
'varying vec4 fsColor; ' +
|
||
|
|
'void main() { ' +
|
||
|
|
' gl_PointSize = 1.0; ' +
|
||
|
|
' gl_Position = vec4(position, 1.0); ' +
|
||
|
|
' fsColor = color; ' +
|
||
|
|
'}';
|
||
|
|
var fs =
|
||
|
|
'varying vec4 fsColor; ' +
|
||
|
|
'void main() { ' +
|
||
|
|
' gl_FragColor = fsColor; ' +
|
||
|
|
'}';
|
||
|
|
sp = ShaderProgram.fromCache({
|
||
|
|
context : context,
|
||
|
|
vertexShaderSource : vs,
|
||
|
|
fragmentShaderSource : fs,
|
||
|
|
attributeLocations : attributeLocations
|
||
|
|
});
|
||
|
|
|
||
|
|
ClearCommand.ALL.execute(context);
|
||
|
|
expect(context).toReadPixels([0, 0, 0, 255]);
|
||
|
|
|
||
|
|
var command = new DrawCommand({
|
||
|
|
primitiveType : PrimitiveType.POINTS,
|
||
|
|
shaderProgram : sp,
|
||
|
|
vertexArray : va,
|
||
|
|
offset : 0,
|
||
|
|
count : 1
|
||
|
|
});
|
||
|
|
command.execute(context);
|
||
|
|
expect(context).toReadPixels([255, 0, 0, 255]);
|
||
|
|
|
||
|
|
command = new DrawCommand({
|
||
|
|
primitiveType : PrimitiveType.POINTS,
|
||
|
|
shaderProgram : sp,
|
||
|
|
vertexArray : va,
|
||
|
|
offset : 1,
|
||
|
|
count : 1
|
||
|
|
});
|
||
|
|
command.execute(context);
|
||
|
|
expect(context).toReadPixels([0, 255, 0, 255]);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('sorts interleaved attributes from large to small components (3)', function() {
|
||
|
|
var geometry = new Geometry({
|
||
|
|
attributes : {
|
||
|
|
unsignedByteAttribute : new GeometryAttribute({
|
||
|
|
componentDatatype : ComponentDatatype.UNSIGNED_BYTE,
|
||
|
|
componentsPerAttribute : 2,
|
||
|
|
values : [1, 2]
|
||
|
|
}),
|
||
|
|
unsignedShortAttribute : new GeometryAttribute({
|
||
|
|
componentDatatype : ComponentDatatype.UNSIGNED_SHORT,
|
||
|
|
componentsPerAttribute : 1,
|
||
|
|
values : [3]
|
||
|
|
}),
|
||
|
|
byteAttribute : new GeometryAttribute({
|
||
|
|
componentDatatype : ComponentDatatype.BYTE,
|
||
|
|
componentsPerAttribute : 1,
|
||
|
|
values : [4]
|
||
|
|
}),
|
||
|
|
shortAttribute : new GeometryAttribute({
|
||
|
|
componentDatatype : ComponentDatatype.SHORT,
|
||
|
|
componentsPerAttribute : 1,
|
||
|
|
values : [5]
|
||
|
|
})
|
||
|
|
},
|
||
|
|
primitiveType : PrimitiveType.POINTS
|
||
|
|
});
|
||
|
|
|
||
|
|
var attributeLocations = GeometryPipeline.createAttributeLocations(geometry);
|
||
|
|
var va = VertexArray.fromGeometry({
|
||
|
|
context : context,
|
||
|
|
geometry : geometry,
|
||
|
|
attributeLocations : attributeLocations,
|
||
|
|
interleave : true
|
||
|
|
});
|
||
|
|
|
||
|
|
expect(va.numberOfAttributes).toEqual(4);
|
||
|
|
expect(va.getAttribute(0).vertexBuffer.sizeInBytes).toEqual(8); // Includes 1 byte per-vertex padding
|
||
|
|
|
||
|
|
// Validate via rendering
|
||
|
|
var vs =
|
||
|
|
'attribute vec2 unsignedByteAttribute; ' +
|
||
|
|
'attribute float unsignedShortAttribute; ' +
|
||
|
|
'attribute float byteAttribute; ' +
|
||
|
|
'attribute float shortAttribute; ' +
|
||
|
|
'varying vec4 fsColor; ' +
|
||
|
|
'void main() { ' +
|
||
|
|
' gl_PointSize = 1.0; ' +
|
||
|
|
' gl_Position = vec4(0.0, 0.0, 0.0, 1.0); ' +
|
||
|
|
' fsColor = vec4((unsignedByteAttribute.x == 1.0) && (unsignedByteAttribute.y == 2.0) && (unsignedShortAttribute == 3.0) && (byteAttribute == 4.0) && (shortAttribute == 5.0)); ' +
|
||
|
|
'}';
|
||
|
|
var fs =
|
||
|
|
'varying vec4 fsColor; ' +
|
||
|
|
'void main() { ' +
|
||
|
|
' gl_FragColor = fsColor; ' +
|
||
|
|
'}';
|
||
|
|
sp = ShaderProgram.fromCache({
|
||
|
|
context : context,
|
||
|
|
vertexShaderSource : vs,
|
||
|
|
fragmentShaderSource : fs,
|
||
|
|
attributeLocations : attributeLocations
|
||
|
|
});
|
||
|
|
|
||
|
|
ClearCommand.ALL.execute(context);
|
||
|
|
expect(context).toReadPixels([0, 0, 0, 255]);
|
||
|
|
|
||
|
|
var command = new DrawCommand({
|
||
|
|
primitiveType : PrimitiveType.POINTS,
|
||
|
|
shaderProgram : sp,
|
||
|
|
vertexArray : va
|
||
|
|
});
|
||
|
|
command.execute(context);
|
||
|
|
expect(context).toReadPixels([255, 255, 255, 255]);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('creates a custom interleaved vertex', function() {
|
||
|
|
var geometry = new Geometry({
|
||
|
|
attributes : {
|
||
|
|
position : new GeometryAttribute({
|
||
|
|
componentDatatype : ComponentDatatype.FLOAT,
|
||
|
|
componentsPerAttribute : 3,
|
||
|
|
values : [0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
|
||
|
|
}),
|
||
|
|
color : new GeometryAttribute({
|
||
|
|
componentDatatype : ComponentDatatype.UNSIGNED_BYTE,
|
||
|
|
componentsPerAttribute : 3,
|
||
|
|
normalize : true,
|
||
|
|
values : [255, 0, 0, 0, 255, 0]
|
||
|
|
}),
|
||
|
|
normal : new GeometryAttribute({
|
||
|
|
componentDatatype : ComponentDatatype.FLOAT,
|
||
|
|
componentsPerAttribute : 3,
|
||
|
|
values : [1.0, 0.0, 0.0, 0.0, 1.0, 0.0]
|
||
|
|
}),
|
||
|
|
temperature : new GeometryAttribute({
|
||
|
|
componentDatatype : ComponentDatatype.UNSIGNED_SHORT,
|
||
|
|
componentsPerAttribute : 1,
|
||
|
|
values : [75, 100]
|
||
|
|
})
|
||
|
|
},
|
||
|
|
primitiveType : PrimitiveType.POINTS
|
||
|
|
});
|
||
|
|
|
||
|
|
var attributeLocations = GeometryPipeline.createAttributeLocations(geometry);
|
||
|
|
var va = VertexArray.fromGeometry({
|
||
|
|
context : context,
|
||
|
|
geometry : geometry,
|
||
|
|
attributeLocations : attributeLocations,
|
||
|
|
interleave : true
|
||
|
|
});
|
||
|
|
|
||
|
|
expect(va.getAttribute(0).vertexBuffer.sizeInBytes).toEqual(2 * 32); // Includes 3 byte per-vertex padding
|
||
|
|
|
||
|
|
// Validate via rendering
|
||
|
|
var vs =
|
||
|
|
'attribute vec3 position; ' +
|
||
|
|
'attribute vec3 color; ' +
|
||
|
|
'attribute vec3 normal; ' +
|
||
|
|
'attribute float temperature; ' +
|
||
|
|
'varying vec4 fsColor; ' +
|
||
|
|
'void main() { ' +
|
||
|
|
' gl_PointSize = 1.0; ' +
|
||
|
|
' gl_Position = vec4(position, 1.0); ' +
|
||
|
|
' if ((normal == vec3(1.0, 0.0, 0.0)) && (temperature == 75.0)) { ' +
|
||
|
|
' fsColor = vec4(color, 1.0); ' +
|
||
|
|
' } ' +
|
||
|
|
' else {' +
|
||
|
|
' fsColor = vec4(1.0); ' +
|
||
|
|
' }' +
|
||
|
|
'}';
|
||
|
|
var fs =
|
||
|
|
'varying vec4 fsColor; ' +
|
||
|
|
'void main() { ' +
|
||
|
|
' gl_FragColor = fsColor; ' +
|
||
|
|
'}';
|
||
|
|
sp = ShaderProgram.fromCache({
|
||
|
|
context : context,
|
||
|
|
vertexShaderSource : vs,
|
||
|
|
fragmentShaderSource : fs,
|
||
|
|
attributeLocations : attributeLocations
|
||
|
|
});
|
||
|
|
|
||
|
|
ClearCommand.ALL.execute(context);
|
||
|
|
expect(context).toReadPixels([0, 0, 0, 255]);
|
||
|
|
|
||
|
|
var command = new DrawCommand({
|
||
|
|
primitiveType : PrimitiveType.POINTS,
|
||
|
|
shaderProgram : sp,
|
||
|
|
vertexArray : va,
|
||
|
|
offset : 0,
|
||
|
|
count : 1
|
||
|
|
});
|
||
|
|
command.execute(context);
|
||
|
|
expect(context).toReadPixels([255, 0, 0, 255]);
|
||
|
|
|
||
|
|
var vs2 =
|
||
|
|
'attribute vec3 position; ' +
|
||
|
|
'attribute vec3 color; ' +
|
||
|
|
'attribute vec3 normal; ' +
|
||
|
|
'attribute float temperature; ' +
|
||
|
|
'varying vec4 fsColor; ' +
|
||
|
|
'void main() { ' +
|
||
|
|
' gl_PointSize = 1.0; ' +
|
||
|
|
' gl_Position = vec4(position, 1.0); ' +
|
||
|
|
' if ((normal == vec3(0.0, 1.0, 0.0)) && (temperature == 100.0)) { ' +
|
||
|
|
' fsColor = vec4(color, 1.0); ' +
|
||
|
|
' } ' +
|
||
|
|
' else {' +
|
||
|
|
' fsColor = vec4(1.0); ' +
|
||
|
|
' }' +
|
||
|
|
'}';
|
||
|
|
sp = sp.destroy();
|
||
|
|
sp = ShaderProgram.fromCache({
|
||
|
|
context : context,
|
||
|
|
vertexShaderSource : vs2,
|
||
|
|
fragmentShaderSource : fs,
|
||
|
|
attributeLocations : attributeLocations
|
||
|
|
});
|
||
|
|
|
||
|
|
command = new DrawCommand({
|
||
|
|
primitiveType : PrimitiveType.POINTS,
|
||
|
|
shaderProgram : sp,
|
||
|
|
vertexArray : va,
|
||
|
|
offset : 1,
|
||
|
|
count : 1
|
||
|
|
});
|
||
|
|
command.execute(context);
|
||
|
|
expect(context).toReadPixels([0, 255, 0, 255]);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('creates an index buffer', function() {
|
||
|
|
var geometry = new Geometry({
|
||
|
|
attributes : {},
|
||
|
|
indices : [0],
|
||
|
|
primitiveType : PrimitiveType.POINTS
|
||
|
|
});
|
||
|
|
|
||
|
|
var va = VertexArray.fromGeometry({
|
||
|
|
context : context,
|
||
|
|
geometry : geometry
|
||
|
|
});
|
||
|
|
|
||
|
|
expect(va.numberOfAttributes).toEqual(0);
|
||
|
|
expect(va.indexBuffer).toBeDefined();
|
||
|
|
expect(va.indexBuffer.usage).toEqual(BufferUsage.DYNAMIC_DRAW); // Default
|
||
|
|
expect(va.indexBuffer.indexDatatype).toEqual(IndexDatatype.UNSIGNED_SHORT);
|
||
|
|
expect(va.indexBuffer.numberOfIndices).toEqual(geometry.indices.length);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('throws with different number of interleaved attributes', function() {
|
||
|
|
var geometry = new Geometry({
|
||
|
|
attributes : {
|
||
|
|
position : new GeometryAttribute({
|
||
|
|
componentDatatype : ComponentDatatype.FLOAT,
|
||
|
|
componentsPerAttribute : 1,
|
||
|
|
values : [0.0]
|
||
|
|
}),
|
||
|
|
normal : new GeometryAttribute({
|
||
|
|
componentDatatype : ComponentDatatype.FLOAT,
|
||
|
|
componentsPerAttribute : 1,
|
||
|
|
values : [1.0, 2.0]
|
||
|
|
})
|
||
|
|
},
|
||
|
|
primitiveType : PrimitiveType.POINTS
|
||
|
|
});
|
||
|
|
|
||
|
|
expect(function() {
|
||
|
|
return VertexArray.fromGeometry({
|
||
|
|
context : context,
|
||
|
|
geometry : geometry,
|
||
|
|
interleave : true
|
||
|
|
});
|
||
|
|
}).toThrowRuntimeError();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('throws with duplicate indices', function() {
|
||
|
|
var geometry = new Geometry({
|
||
|
|
attributes : {
|
||
|
|
position : new GeometryAttribute({
|
||
|
|
componentDatatype : ComponentDatatype.FLOAT,
|
||
|
|
componentsPerAttribute : 1,
|
||
|
|
values : [0.0]
|
||
|
|
}),
|
||
|
|
normal : new GeometryAttribute({
|
||
|
|
componentDatatype : ComponentDatatype.FLOAT,
|
||
|
|
componentsPerAttribute : 1,
|
||
|
|
values : [1.0]
|
||
|
|
})
|
||
|
|
},
|
||
|
|
primitiveType : PrimitiveType.POINTS
|
||
|
|
});
|
||
|
|
|
||
|
|
expect(function() {
|
||
|
|
return VertexArray.fromGeometry({
|
||
|
|
context : context,
|
||
|
|
geometry : geometry,
|
||
|
|
attributeLocations : {
|
||
|
|
position : 0,
|
||
|
|
normal : 0
|
||
|
|
}
|
||
|
|
});
|
||
|
|
}).toThrowDeveloperError();
|
||
|
|
});
|
||
|
|
}, 'WebGL');
|