Skip to content

Commit

Permalink
refactor(BufferGeometry): refactor attribute handling
Browse files Browse the repository at this point in the history
  • Loading branch information
johh committed Feb 29, 2020
1 parent 7865115 commit 182d33e
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 41 deletions.
72 changes: 45 additions & 27 deletions src/lib/BufferGeometry.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { TriangleDrawMode } from './Enums';
import Material from './Material';


interface BufferGeometryProps {
verts: number[];
Expand All @@ -15,18 +17,25 @@ type BufferAttributeList = {
};


type BufferAttributeReference = {
name: string,
size: number,
offset: number,
};


export default class BufferGeometry {
protected verts: number[];
protected attributes: BufferAttributeList;
protected inputAttributes: BufferAttributeList;
protected attributes: BufferAttributeReference[];
protected bufferData: Float32Array;
protected buffer: WebGLBuffer;
protected indices: Uint16Array;
protected indexBuffer: WebGLBuffer;
protected mode: TriangleDrawMode;
protected stride: number;
public attributeNames: string[];
protected vertexName: string;
private gl: WebGLRenderingContext;
private attributeSetupFunctions: Function[] = [];

constructor( props: BufferGeometryProps ) {
const {
Expand All @@ -41,8 +50,8 @@ export default class BufferGeometry {
this.verts = verts;
this.mode = mode;
this.stride = stride;
this.attributes = attributes;
this.attributeNames = [vertexName, ...Object.keys( attributes )];
this.inputAttributes = attributes;
this.vertexName = vertexName;

if ( indices ) this.indices = new Uint16Array( indices );
}
Expand All @@ -54,21 +63,36 @@ export default class BufferGeometry {
const gl = this.gl;

let data = [].concat( this.verts );
const sizes: number[] = [this.stride];
let offset = this.verts.length * 4;

this.attributes = [];
this.attributes.push({
name: this.vertexName,
size: this.stride,
offset: 0,
});


Object.values( this.attributes ).forEach( ( attribute, i ) => {
Object.keys( this.inputAttributes ).forEach( ( name ) => {
const attribute = this.inputAttributes[name];
const _offset = offset;
let size = attribute.length / ( this.verts.length / this.stride );

if ( size % 1 !== 0 ) {
console.warn( `[WEBGL] Unsupported attribute size in slot ${i}, filling with zeroes` );
console.warn( `[WEBGL] Unsupported attribute size for "${name}", filling with zeroes` );
size = 1;
data = data.concat( Array( this.verts.length / this.stride ).fill( 0 ) );
} else {
data = data.concat( attribute );
}

sizes.push( size );
this.attributes.push({
name,
size,
offset: _offset,
});

offset += ( this.verts.length / this.stride ) * size * 4;
});

this.bufferData = new Float32Array( data );
Expand All @@ -77,20 +101,6 @@ export default class BufferGeometry {
gl.bindBuffer( gl.ARRAY_BUFFER, this.buffer );
gl.bufferData( gl.ARRAY_BUFFER, this.bufferData, gl.STATIC_DRAW );

let offset = 0;

sizes.forEach( ( size, i ) => {
const _offset = offset;

this.attributeSetupFunctions.push( () => {
gl.bindBuffer( gl.ARRAY_BUFFER, this.buffer );
gl.enableVertexAttribArray( i );
gl.vertexAttribPointer( i, size, gl.FLOAT, false, 0, _offset );
});

offset += ( this.verts.length / this.stride ) * size * 4;
});


if ( this.indices ) {
this.indexBuffer = gl.createBuffer();
Expand All @@ -104,16 +114,24 @@ export default class BufferGeometry {
}


private prepare() {
this.attributeSetupFunctions.forEach( f => f() );
private prepare( material: Material ) {
const gl = this.gl;

this.attributes.forEach( ( attribute ) => {
const index = material.getAttributeLocation( attribute.name );

gl.bindBuffer( gl.ARRAY_BUFFER, this.buffer );
gl.enableVertexAttribArray( index );
gl.vertexAttribPointer( index, attribute.size, gl.FLOAT, false, 0, attribute.offset );
});
}


public draw( gl: WebGLRenderingContext ) {
public draw( gl: WebGLRenderingContext, material: Material ) {
this.gl = gl;

gl.bindBuffer( gl.ARRAY_BUFFER, this.upload() );
this.prepare();
this.prepare( material );

if ( this.indices ) {
gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer );
Expand Down
22 changes: 12 additions & 10 deletions src/lib/Material.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ export default class Material {
private gl: WebGLRenderingContext;
private program: WebGLProgram;
private uniforms = new Map<string, UniformReference>();
private attributeLocations = new Map<string, number>();
private queuedUniforms: UniformList = {};
private textures: Texture[] = [];
public readonly isMaterial = true;
Expand All @@ -124,10 +125,10 @@ export default class Material {
}


private compile( attributes: string[]) {
private compile() {
if ( this.program ) return this.program;

const cacheKey = this.vertexSrc + this.fragmentSrc + attributes.join( ',' );
const cacheKey = this.vertexSrc + this.fragmentSrc;

if ( programCache.has( cacheKey ) ) {
this.program = programCache.get( cacheKey );
Expand All @@ -142,8 +143,6 @@ export default class Material {
gl.attachShader( this.program, vertexShader );
gl.attachShader( this.program, fragmentShader );

this.mapAttributes( attributes );

gl.linkProgram( this.program );

if ( !gl.getProgramParameter( this.program, gl.LINK_STATUS ) ) {
Expand All @@ -163,12 +162,15 @@ export default class Material {
}


private mapAttributes( attributes: string[]) {
public getAttributeLocation( name: string ) {
const gl = this.gl;

attributes.forEach( ( name, i ) => {
gl.bindAttribLocation( this.program, i, name );
});
if ( this.attributeLocations.has( name ) ) return this.attributeLocations.get( name );

const loc = gl.getAttribLocation( this.program, name );
this.attributeLocations.set( name, loc );

return loc;
}


Expand Down Expand Up @@ -221,10 +223,10 @@ export default class Material {
}


public use( gl: WebGLRenderingContext, attributes: string[] = []) {
public use( gl: WebGLRenderingContext ) {
this.gl = gl;

gl.useProgram( this.compile( attributes ) );
gl.useProgram( this.compile() );
this.commitUniforms();
this.bindTextures();
}
Expand Down
4 changes: 2 additions & 2 deletions src/lib/Renderable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,8 @@ export default class Renderable extends TransformNode {
break;
}

this.material.use( gl, this.geometry.attributeNames );
this.geometry.draw( gl );
this.material.use( gl );
this.geometry.draw( gl, this.material );

if ( !this.depthTest ) gl.enable( gl.DEPTH_TEST );
if ( !this.depthWrite ) gl.depthMask( true );
Expand Down
4 changes: 2 additions & 2 deletions src/lib/Renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,8 @@ export default class Renderer {
this.gl.bindFramebuffer( this.gl.FRAMEBUFFER, null );
}

material.use( this.gl, geometry.attributeNames );
geometry.draw( this.gl );
material.use( this.gl );
geometry.draw( this.gl, material );
}


Expand Down

0 comments on commit 182d33e

Please sign in to comment.