Transform Feedback in context of Three.js

Hey All,

I came across this post and saw the PR and related discussion on github which seems to be ending in a limbo.

I created this post to hopefully discuss possible solution that would be inline with current three.js setup (mainly it’s caching mechanisms). I have spent some time thinking how this feature could be interweaved in current three.js setup and here are some bullet points how I would see it.

By no means this is a ready solution but it gives some starting point for the discussion to move this topic forward.

I would appreciate your feedback on proposed solution and to know if there is anything going on in this matter? Last post from @Mugen87 on GitHub points out some idea but not sure if this has been crystallised in a form of code? (branch?)

Below some principles of my idea:

  • include transform feedback object ( TFO, result of gl.createTransformFeedback() ) as part of WebGLBindingState (similar to current object property (VAO)),
  • augment BufferAttribute with a property, for example transformFeedbackVaryingName of type string, which would be indication that the attribute should have corresponding TF buffer created. User would call bufferAttribute.transformFeedbackVaryingName.set('myVarying') when creating BufferAttribute and setting the name as defined in the shader (assuming ShaderMaterial usage here), this could be ‘automated’ further when parsing shaders from chunk maybe,
  • BufferGeometry would keep track of the names of its attribute TF Varyings (ie. by defining getter tfVaryingNames with some clever caching maybe)
  • augment WebGLProgram with conditionally executed code:
   gl.transformFeedbackVaryings(
     program,
     parameters.tfVaryingNames,
     gl.SEPARATE_ATTRIBS // additional parameter would define this?
   );

if parameters.tfVaryingNames is present (the parameter would be defined in WebGLPrograms from geometry.tfVaryingNames) as other parameters there,

  • augment WebGLAttributes createBuffer output to contain additional tfBuffer property, similarly to buffer but here data would be written to by GPU,
  • when calling bindingStates.setup in WebGLRenderer there would be additional call, while looping the attributes (same as it is doing now for vao to set vertexAttribPointer etc.),
       gl.bindBufferBase(
         gl.TRANSFORM_FEEDBACK_BUFFER,
         program.location,
         tfBuffer 
       );
  • (optional) create separate transformFeedbackRenderer, that would wrap gl[begin / end ]TransformFeedback around drawArrays call, the renderer would be set similarly as currently indexedBufferRenderer is set
  • create flipping mechanism that would allow switching read/write from/to buffer or tfBuffer so the actual transform feedback can be utilised (in WebGLBindingStates which would provide tick function used by WebGLRenderer to flip buffers.

Here I have some performance consideration:

is it better (three.js context, performance-wise) to flip buffers only (as described above) and allowing the WebGLRenderer to re-bind and re-configure each attribute in the binding state VAO / TFO ? Does this not contradict the idea of VAO which was created so we don’t need to rebind each buffer?