Hi all,
Something that popped into my head awhile back while preparing to do some extension work on existing shader code was how binding data/buffers on the CPU–TS/JS side to the GPU level can be a hassle and there’s a lot of maintenance and manual updating going on while defining uniforms and updating on bind.
Some inspiration for this framework comes from buffer message protocols like protobuf, flatbuffers, capnp. I wanted to be able to create a binding between the two languages (JS/TS and GLSL) to create an object in JS/TS easily and have it be represented/accessible/automatically updated in the GPU side to avoid manually managing each uniform and track indices/strides/”types”
I’ve been working on this for about a week and still have a lot to do in terms of naming/ergonomics/testing. The WebGPU side has some kinks to work out as well, but this is the PG I am working from
The gist of it is being able to define objects in TS/JS like this and bind them to a ShaderMaterial automatically. This could be extended to NME likely as well. Wanted to share this and see if anyone has any thoughts on usefulness and direction.
// TS version - direct binding with decorators
// @gpuStruct({ name: 'TestStruct' })
// class TestStruct extends GPURecord {
// constructor(engine: BABYLON.Engine) {
// super(engine);
// }
// @field(1, 'vec4') color!: Float32Array; // live view (Float32Array)
// @field(2, 'f32') lifetime!: number; // scalar
// @field(3, { varOf: 'f32' }) times!: number[]; // array
// }
// JS compatible version with schema builder
class ChildInstance extends GPURecord {
static schema = new GPUStructSchemaBuilder('ChildInstance')
.registerField(1, 'id', 'u32')
.registerField(2, 'color', 'f32')
.build();
constructor(engine) {
super(engine);
}
}
class TestStruct extends GPURecord {
static schema = new GPUStructSchemaBuilder('TestStruct')
.registerField(1, 'color', 'vec4')
.registerField(2, 'lifetime', 'f32')
.registerField(3, 'times', { varOf: 'f32' })
.registerField(4, 'instances', { varOf: { structOf: ChildInstance } })
.build();
constructor(engine) {
super(engine);
}
}
Will be continuing work here and providing updates as they come