|
@@ -42,6 +42,10 @@ class WebGLBackend extends Backend {
|
|
this.state = new WebGLState( this );
|
|
this.state = new WebGLState( this );
|
|
this.utils = new WebGLUtils( this );
|
|
this.utils = new WebGLUtils( this );
|
|
|
|
|
|
|
|
+ this.vaoCache = {};
|
|
|
|
+ this.transformFeedbackCache = {};
|
|
|
|
+ this.discard = false;
|
|
|
|
+
|
|
this.extensions.get( 'EXT_color_buffer_float' );
|
|
this.extensions.get( 'EXT_color_buffer_float' );
|
|
this._currentContext = null;
|
|
this._currentContext = null;
|
|
|
|
|
|
@@ -350,26 +354,76 @@ class WebGLBackend extends Backend {
|
|
|
|
|
|
beginCompute( /*computeGroup*/ ) {
|
|
beginCompute( /*computeGroup*/ ) {
|
|
|
|
|
|
- console.warn( 'Abstract class.' );
|
|
|
|
|
|
+ const gl = this.gl;
|
|
|
|
+
|
|
|
|
+ gl.bindFramebuffer( gl.FRAMEBUFFER, null );
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
- compute( /*computeGroup, computeNode, bindings, pipeline*/ ) {
|
|
|
|
|
|
+ compute( computeGroup, computeNode, bindings, pipeline ) {
|
|
|
|
|
|
- console.warn( 'Abstract class.' );
|
|
|
|
|
|
+ const gl = this.gl;
|
|
|
|
+
|
|
|
|
+ if ( ! this.discard ) {
|
|
|
|
+
|
|
|
|
+ // required here to handle async behaviour of render.compute()
|
|
|
|
+ gl.enable( gl.RASTERIZER_DISCARD );
|
|
|
|
+ this.discard = true;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ const { programGPU, transformBuffers, attributes } = this.get( pipeline );
|
|
|
|
+
|
|
|
|
+ const vaoKey = this._getVaoKey( null, attributes );
|
|
|
|
+
|
|
|
|
+ let vaoGPU = this.vaoCache[ vaoKey ];
|
|
|
|
+
|
|
|
|
+ if ( vaoGPU === undefined ) {
|
|
|
|
+
|
|
|
|
+ this._createVao( null, attributes );
|
|
|
|
+
|
|
|
|
+ } else {
|
|
|
|
+
|
|
|
|
+ gl.bindVertexArray( vaoGPU );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ gl.useProgram( programGPU );
|
|
|
|
+
|
|
|
|
+ this._bindUniforms( bindings );
|
|
|
|
+
|
|
|
|
+ const transformFeedbackGPU = this._getTransformFeedback( transformBuffers );
|
|
|
|
+
|
|
|
|
+ gl.bindTransformFeedback( gl.TRANSFORM_FEEDBACK, transformFeedbackGPU );
|
|
|
|
+ gl.beginTransformFeedback( gl.POINTS );
|
|
|
|
+
|
|
|
|
+ gl.drawArraysInstanced( gl.POINTS, 0, 1, computeNode.count );
|
|
|
|
+
|
|
|
|
+ gl.endTransformFeedback();
|
|
|
|
+ gl.bindTransformFeedback( gl.TRANSFORM_FEEDBACK, null );
|
|
|
|
+
|
|
|
|
+ // switch active buffers
|
|
|
|
+ for ( let i = 0; i < transformBuffers.length; i ++ ) {
|
|
|
|
+
|
|
|
|
+ transformBuffers[ i ].switchBuffers();
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
finishCompute( /*computeGroup*/ ) {
|
|
finishCompute( /*computeGroup*/ ) {
|
|
|
|
|
|
- console.warn( 'Abstract class.' );
|
|
|
|
|
|
+ const gl = this.gl;
|
|
|
|
+
|
|
|
|
+ this.discard = false;
|
|
|
|
+
|
|
|
|
+ gl.disable( gl.RASTERIZER_DISCARD );
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
draw( renderObject, info ) {
|
|
draw( renderObject, info ) {
|
|
|
|
|
|
const { pipeline, material, context } = renderObject;
|
|
const { pipeline, material, context } = renderObject;
|
|
- const { programGPU, vaoGPU } = this.get( pipeline );
|
|
|
|
|
|
+ const { programGPU } = this.get( pipeline );
|
|
|
|
|
|
const { gl, state } = this;
|
|
const { gl, state } = this;
|
|
|
|
|
|
@@ -377,28 +431,34 @@ class WebGLBackend extends Backend {
|
|
|
|
|
|
//
|
|
//
|
|
|
|
|
|
- const bindings = renderObject.getBindings();
|
|
|
|
|
|
+ this._bindUniforms( renderObject.getBindings() );
|
|
|
|
|
|
- for ( const binding of bindings ) {
|
|
|
|
|
|
+ state.setMaterial( material );
|
|
|
|
|
|
- const bindingData = this.get( binding );
|
|
|
|
- const index = bindingData.index;
|
|
|
|
|
|
+ gl.useProgram( programGPU );
|
|
|
|
|
|
- if ( binding.isUniformsGroup || binding.isUniformBuffer ) {
|
|
|
|
|
|
+ //
|
|
|
|
|
|
- gl.bindBufferBase( gl.UNIFORM_BUFFER, index, bindingData.bufferGPU );
|
|
|
|
|
|
+ let vaoGPU = renderObject.staticVao;
|
|
|
|
|
|
- } else if ( binding.isSampledTexture ) {
|
|
|
|
|
|
+ if ( vaoGPU === undefined ) {
|
|
|
|
|
|
- state.bindTexture( bindingData.glTextureType, bindingData.textureGPU, gl.TEXTURE0 + index );
|
|
|
|
|
|
+ const vaoKey = this._getVaoKey( renderObject.getIndex(), renderObject.getAttributes() );
|
|
|
|
+
|
|
|
|
+ vaoGPU = this.vaoCache[ vaoKey ];
|
|
|
|
+
|
|
|
|
+ if ( vaoGPU === undefined ) {
|
|
|
|
+
|
|
|
|
+ let staticVao;
|
|
|
|
+
|
|
|
|
+ ( { vaoGPU, staticVao } = this._createVao( renderObject.getIndex(), renderObject.getAttributes() ) );
|
|
|
|
+
|
|
|
|
+ if ( staticVao ) renderObject.staticVao = vaoGPU;
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
- state.setMaterial( material );
|
|
|
|
-
|
|
|
|
- gl.useProgram( programGPU );
|
|
|
|
gl.bindVertexArray( vaoGPU );
|
|
gl.bindVertexArray( vaoGPU );
|
|
|
|
|
|
//
|
|
//
|
|
@@ -480,7 +540,6 @@ class WebGLBackend extends Backend {
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
info.update( object, indexCount, 1 );
|
|
info.update( object, indexCount, 1 );
|
|
|
|
|
|
} else {
|
|
} else {
|
|
@@ -504,8 +563,6 @@ class WebGLBackend extends Backend {
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
-
|
|
|
|
//
|
|
//
|
|
|
|
|
|
gl.bindVertexArray( null );
|
|
gl.bindVertexArray( null );
|
|
@@ -586,7 +643,7 @@ class WebGLBackend extends Backend {
|
|
const gl = this.gl;
|
|
const gl = this.gl;
|
|
const { stage, code } = program;
|
|
const { stage, code } = program;
|
|
|
|
|
|
- const shader = stage === 'vertex' ? gl.createShader( gl.VERTEX_SHADER ) : gl.createShader( gl.FRAGMENT_SHADER );
|
|
|
|
|
|
+ const shader = stage === 'fragment' ? gl.createShader( gl.FRAGMENT_SHADER ) : gl.createShader( gl.VERTEX_SHADER );
|
|
|
|
|
|
gl.shaderSource( shader, code );
|
|
gl.shaderSource( shader, code );
|
|
gl.compileShader( shader );
|
|
gl.compileShader( shader );
|
|
@@ -634,105 +691,114 @@ class WebGLBackend extends Backend {
|
|
|
|
|
|
// Bindings
|
|
// Bindings
|
|
|
|
|
|
- const bindings = renderObject.getBindings();
|
|
|
|
|
|
+ this._setupBindings( renderObject.getBindings(), programGPU );
|
|
|
|
|
|
- for ( const binding of bindings ) {
|
|
|
|
|
|
+ //
|
|
|
|
|
|
- const bindingData = this.get( binding );
|
|
|
|
- const index = bindingData.index;
|
|
|
|
|
|
+ this.set( pipeline, {
|
|
|
|
+ programGPU
|
|
|
|
+ } );
|
|
|
|
|
|
- if ( binding.isUniformsGroup || binding.isUniformBuffer ) {
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- const location = gl.getUniformBlockIndex( programGPU, binding.name );
|
|
|
|
- gl.uniformBlockBinding( programGPU, location, index );
|
|
|
|
|
|
+ createComputePipeline( computePipeline, bindings ) {
|
|
|
|
|
|
- } else if ( binding.isSampledTexture ) {
|
|
|
|
|
|
+ const gl = this.gl;
|
|
|
|
|
|
- const location = gl.getUniformLocation( programGPU, binding.name );
|
|
|
|
- gl.uniform1i( location, index );
|
|
|
|
|
|
+ // Program
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ const fragmentProgram = {
|
|
|
|
+ stage: 'fragment',
|
|
|
|
+ code: "#version 300 es\nprecision highp float;\nvoid main() {}"
|
|
|
|
+ };
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ this.createProgram( fragmentProgram );
|
|
|
|
|
|
- // VAO
|
|
|
|
|
|
+ const { computeProgram } = computePipeline;
|
|
|
|
|
|
- const vaoGPU = gl.createVertexArray();
|
|
|
|
|
|
+ const programGPU = gl.createProgram();
|
|
|
|
|
|
- const index = renderObject.getIndex();
|
|
|
|
- const attributes = renderObject.getAttributes();
|
|
|
|
|
|
+ const fragmentShader = this.get( fragmentProgram ).shaderGPU;
|
|
|
|
+ const vertexShader = this.get( computeProgram ).shaderGPU;
|
|
|
|
|
|
- gl.bindVertexArray( vaoGPU );
|
|
|
|
|
|
+ const transforms = computeProgram.transforms;
|
|
|
|
|
|
- if ( index !== null ) {
|
|
|
|
|
|
+ const transformVaryingNames = [];
|
|
|
|
+ const transformAttributeNodes = [];
|
|
|
|
|
|
- const indexData = this.get( index );
|
|
|
|
|
|
+ for ( let i = 0; i < transforms.length; i ++ ) {
|
|
|
|
|
|
- gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, indexData.bufferGPU );
|
|
|
|
|
|
+ const transform = transforms[ i ];
|
|
|
|
+
|
|
|
|
+ transformVaryingNames.push( transform.varyingName );
|
|
|
|
+ transformAttributeNodes.push( transform.attributeNode );
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
- for ( let i = 0; i < attributes.length; i ++ ) {
|
|
|
|
|
|
+ gl.attachShader( programGPU, fragmentShader );
|
|
|
|
+ gl.attachShader( programGPU, vertexShader );
|
|
|
|
|
|
- const attribute = attributes[ i ];
|
|
|
|
- const attributeData = this.get( attribute );
|
|
|
|
|
|
+ gl.transformFeedbackVaryings(
|
|
|
|
+ programGPU,
|
|
|
|
+ transformVaryingNames,
|
|
|
|
+ gl.SEPARATE_ATTRIBS,
|
|
|
|
+ );
|
|
|
|
|
|
- gl.bindBuffer( gl.ARRAY_BUFFER, attributeData.bufferGPU );
|
|
|
|
- gl.enableVertexAttribArray( i );
|
|
|
|
|
|
+ gl.linkProgram( programGPU );
|
|
|
|
|
|
- let stride, offset;
|
|
|
|
|
|
+ if ( gl.getProgramParameter( programGPU, gl.LINK_STATUS ) === false ) {
|
|
|
|
|
|
- if ( attribute.isInterleavedBufferAttribute === true ) {
|
|
|
|
|
|
+ console.error( 'THREE.WebGLBackend:', gl.getProgramInfoLog( programGPU ) );
|
|
|
|
|
|
- stride = attribute.data.stride * attributeData.bytesPerElement;
|
|
|
|
- offset = attribute.offset * attributeData.bytesPerElement;
|
|
|
|
|
|
+ console.error( 'THREE.WebGLBackend:', gl.getShaderInfoLog( fragmentShader ) );
|
|
|
|
+ console.error( 'THREE.WebGLBackend:', gl.getShaderInfoLog( vertexShader ) );
|
|
|
|
|
|
- } else {
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- stride = 0;
|
|
|
|
- offset = 0;
|
|
|
|
|
|
+ gl.useProgram( programGPU );
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ // Bindings
|
|
|
|
|
|
- if ( attributeData.isInteger ) {
|
|
|
|
|
|
+ this.createBindings( bindings );
|
|
|
|
|
|
- gl.vertexAttribIPointer( i, attribute.itemSize, attributeData.type, stride, offset );
|
|
|
|
|
|
+ this._setupBindings( bindings, programGPU );
|
|
|
|
|
|
- } else {
|
|
|
|
|
|
+ const attributeNodes = computeProgram.attributes;
|
|
|
|
+ const attributes = [];
|
|
|
|
+ const transformBuffers = [];
|
|
|
|
|
|
- gl.vertexAttribPointer( i, attribute.itemSize, attributeData.type, attribute.normalized, stride, offset );
|
|
|
|
|
|
+ for ( let i = 0; i < attributeNodes.length; i ++ ) {
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ const attribute = attributeNodes[ i ].node.attribute;
|
|
|
|
|
|
- if ( attribute.isInstancedBufferAttribute && ! attribute.isInterleavedBufferAttribute ) {
|
|
|
|
|
|
+ attributes.push( attribute );
|
|
|
|
|
|
- gl.vertexAttribDivisor( i, attribute.meshPerAttribute );
|
|
|
|
|
|
+ if ( ! this.has( attribute ) ) this.attributeUtils.createAttribute( attribute, gl.ARRAY_BUFFER );
|
|
|
|
|
|
- } else if ( attribute.isInterleavedBufferAttribute && attribute.data.isInstancedInterleavedBuffer ) {
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- gl.vertexAttribDivisor( i, attribute.data.meshPerAttribute );
|
|
|
|
|
|
+ for ( let i = 0; i < transformAttributeNodes.length; i ++ ) {
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ const attribute = transformAttributeNodes[ i ].attribute;
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ if ( ! this.has( attribute ) ) this.attributeUtils.createAttribute( attribute, gl.ARRAY_BUFFER );
|
|
|
|
|
|
- gl.bindVertexArray( null );
|
|
|
|
|
|
+ const attributeData = this.get( attribute );
|
|
|
|
+
|
|
|
|
+ transformBuffers.push( attributeData );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
|
|
//
|
|
//
|
|
|
|
|
|
- this.set( pipeline, {
|
|
|
|
|
|
+ this.set( computePipeline, {
|
|
programGPU,
|
|
programGPU,
|
|
- vaoGPU
|
|
|
|
|
|
+ transformBuffers,
|
|
|
|
+ attributes
|
|
} );
|
|
} );
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
- createComputePipeline( /*computePipeline, bindings*/ ) {
|
|
|
|
-
|
|
|
|
- console.warn( 'Abstract class.' );
|
|
|
|
-
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
createBindings( bindings ) {
|
|
createBindings( bindings ) {
|
|
|
|
|
|
this.updateBindings( bindings );
|
|
this.updateBindings( bindings );
|
|
@@ -807,15 +873,17 @@ class WebGLBackend extends Backend {
|
|
|
|
|
|
createAttribute( attribute ) {
|
|
createAttribute( attribute ) {
|
|
|
|
|
|
|
|
+ if ( this.has( attribute ) ) return;
|
|
|
|
+
|
|
const gl = this.gl;
|
|
const gl = this.gl;
|
|
|
|
|
|
this.attributeUtils.createAttribute( attribute, gl.ARRAY_BUFFER );
|
|
this.attributeUtils.createAttribute( attribute, gl.ARRAY_BUFFER );
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
- createStorageAttribute( /*attribute*/ ) {
|
|
|
|
|
|
+ createStorageAttribute( attribute ) {
|
|
|
|
|
|
- console.warn( 'Abstract class.' );
|
|
|
|
|
|
+ //console.warn( 'Abstract class.' );
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1026,6 +1094,197 @@ class WebGLBackend extends Backend {
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+
|
|
|
|
+ _getVaoKey( index, attributes ) {
|
|
|
|
+
|
|
|
|
+ let key = [];
|
|
|
|
+
|
|
|
|
+ if ( index !== null ) {
|
|
|
|
+
|
|
|
|
+ const indexData = this.get( index );
|
|
|
|
+
|
|
|
|
+ key += ':' + indexData.id;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ for ( let i = 0; i < attributes.length; i ++ ) {
|
|
|
|
+
|
|
|
|
+ const attributeData = this.get( attributes[ i ] );
|
|
|
|
+
|
|
|
|
+ key += ':' + attributeData.id;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return key;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ _createVao( index, attributes ) {
|
|
|
|
+
|
|
|
|
+ const { gl } = this;
|
|
|
|
+
|
|
|
|
+ const vaoGPU = gl.createVertexArray();
|
|
|
|
+ let key = '';
|
|
|
|
+
|
|
|
|
+ let staticVao = true;
|
|
|
|
+
|
|
|
|
+ gl.bindVertexArray( vaoGPU );
|
|
|
|
+
|
|
|
|
+ if ( index !== null ) {
|
|
|
|
+
|
|
|
|
+ const indexData = this.get( index );
|
|
|
|
+
|
|
|
|
+ gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, indexData.bufferGPU );
|
|
|
|
+
|
|
|
|
+ key += ':' + indexData.id;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ for ( let i = 0; i < attributes.length; i ++ ) {
|
|
|
|
+
|
|
|
|
+ const attribute = attributes[ i ];
|
|
|
|
+ const attributeData = this.get( attribute );
|
|
|
|
+
|
|
|
|
+ key += ':' + attributeData.id;
|
|
|
|
+
|
|
|
|
+ gl.bindBuffer( gl.ARRAY_BUFFER, attributeData.bufferGPU );
|
|
|
|
+ gl.enableVertexAttribArray( i );
|
|
|
|
+
|
|
|
|
+ if ( attribute.isStorageBufferAttribute ) staticVao = false;
|
|
|
|
+
|
|
|
|
+ let stride, offset;
|
|
|
|
+
|
|
|
|
+ if ( attribute.isInterleavedBufferAttribute === true ) {
|
|
|
|
+
|
|
|
|
+ stride = attribute.data.stride * attributeData.bytesPerElement;
|
|
|
|
+ offset = attribute.offset * attributeData.bytesPerElement;
|
|
|
|
+
|
|
|
|
+ } else {
|
|
|
|
+
|
|
|
|
+ stride = 0;
|
|
|
|
+ offset = 0;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if ( attributeData.isInteger ) {
|
|
|
|
+
|
|
|
|
+ gl.vertexAttribIPointer( i, attribute.itemSize, attributeData.type, stride, offset );
|
|
|
|
+
|
|
|
|
+ } else {
|
|
|
|
+
|
|
|
|
+ gl.vertexAttribPointer( i, attribute.itemSize, attributeData.type, attribute.normalized, stride, offset );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if ( attribute.isInstancedBufferAttribute && ! attribute.isInterleavedBufferAttribute ) {
|
|
|
|
+
|
|
|
|
+ gl.vertexAttribDivisor( i, attribute.meshPerAttribute );
|
|
|
|
+
|
|
|
|
+ } else if ( attribute.isInterleavedBufferAttribute && attribute.data.isInstancedInterleavedBuffer ) {
|
|
|
|
+
|
|
|
|
+ gl.vertexAttribDivisor( i, attribute.data.meshPerAttribute );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ gl.bindBuffer( gl.ARRAY_BUFFER, null );
|
|
|
|
+
|
|
|
|
+ this.vaoCache[ key ] = vaoGPU;
|
|
|
|
+
|
|
|
|
+ return { vaoGPU, staticVao };
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ _getTransformFeedback( transformBuffers ) {
|
|
|
|
+
|
|
|
|
+ let key = '';
|
|
|
|
+
|
|
|
|
+ for ( let i = 0; i < transformBuffers.length; i ++ ) {
|
|
|
|
+
|
|
|
|
+ key += ':' + transformBuffers[ i ].id;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ let transformFeedbackGPU = this.transformFeedbackCache[ key ];
|
|
|
|
+
|
|
|
|
+ if ( transformFeedbackGPU !== undefined ) {
|
|
|
|
+
|
|
|
|
+ return transformFeedbackGPU;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ const gl = this.gl;
|
|
|
|
+
|
|
|
|
+ transformFeedbackGPU = gl.createTransformFeedback();
|
|
|
|
+
|
|
|
|
+ gl.bindTransformFeedback( gl.TRANSFORM_FEEDBACK, transformFeedbackGPU );
|
|
|
|
+
|
|
|
|
+ for ( let i = 0; i < transformBuffers.length; i ++ ) {
|
|
|
|
+
|
|
|
|
+ const attributeData = transformBuffers[ i ];
|
|
|
|
+
|
|
|
|
+ gl.bindBufferBase( gl.TRANSFORM_FEEDBACK_BUFFER, i, attributeData.transformBuffer );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ gl.bindTransformFeedback( gl.TRANSFORM_FEEDBACK, null );
|
|
|
|
+
|
|
|
|
+ this.transformFeedbackCache[ key ] = transformFeedbackGPU;
|
|
|
|
+
|
|
|
|
+ return transformFeedbackGPU;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ _setupBindings( bindings, programGPU ) {
|
|
|
|
+
|
|
|
|
+ const gl = this.gl;
|
|
|
|
+
|
|
|
|
+ for ( const binding of bindings ) {
|
|
|
|
+
|
|
|
|
+ const bindingData = this.get( binding );
|
|
|
|
+ const index = bindingData.index;
|
|
|
|
+
|
|
|
|
+ if ( binding.isUniformsGroup || binding.isUniformBuffer ) {
|
|
|
|
+
|
|
|
|
+ const location = gl.getUniformBlockIndex( programGPU, binding.name );
|
|
|
|
+ gl.uniformBlockBinding( programGPU, location, index );
|
|
|
|
+
|
|
|
|
+ } else if ( binding.isSampledTexture ) {
|
|
|
|
+
|
|
|
|
+ const location = gl.getUniformLocation( programGPU, binding.name );
|
|
|
|
+ gl.uniform1i( location, index );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ _bindUniforms( bindings ) {
|
|
|
|
+
|
|
|
|
+ const { gl, state } = this;
|
|
|
|
+
|
|
|
|
+ for ( const binding of bindings ) {
|
|
|
|
+
|
|
|
|
+ const bindingData = this.get( binding );
|
|
|
|
+ const index = bindingData.index;
|
|
|
|
+
|
|
|
|
+ if ( binding.isUniformsGroup || binding.isUniformBuffer ) {
|
|
|
|
+
|
|
|
|
+ gl.bindBufferBase( gl.UNIFORM_BUFFER, index, bindingData.bufferGPU );
|
|
|
|
+
|
|
|
|
+ } else if ( binding.isSampledTexture ) {
|
|
|
|
+
|
|
|
|
+ state.bindTexture( bindingData.glTextureType, bindingData.textureGPU, gl.TEXTURE0 + index );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
}
|
|
}
|
|
|
|
|
|
export default WebGLBackend;
|
|
export default WebGLBackend;
|