Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WEBGL2] Transform feedback #14416

Closed
fernandojsg opened this issue Jul 4, 2018 · 8 comments
Closed

[WEBGL2] Transform feedback #14416

fernandojsg opened this issue Jul 4, 2018 · 8 comments

Comments

@fernandojsg
Copy link
Collaborator

fernandojsg commented Jul 4, 2018

I'm working on implementing transform feedback support on top of the WebGLRenderer to WebGL2 proposal.

I would like to get some feedback from the community about the following two approaches:

  1. We'll have something like THREE.TransformFeedback and we will call it with a BufferGeometry and a Program:
var geometry = new THREE.BufferGeometry();
var program = // A program with out varyings
var tf = new THREE.TransformFeedback(geometry, program);

...
renderLoop() {
    tf.tick(); 
    scene.render();
}

THREE.TransformFeedback.prototype.tick = function () {
    bindBuffersAndAttribs();
    gl.enable(gl.RASTERIZER_DISCARD);
    bindTransformFeedback(this.transformFeedback);
    drawCall(currentGeometry, transformFeedbackProgram);
    gl.disable(gl.RASTERIZER_DISCARD);
    unbindBuffersAndAttribs();
}

The constructor will create a copy of the buffergeometry that will then be used on tick to pingpong between these two geometries.
As you can spot, we're calling RASTERIZER_DISCARD as we don't want to draw anything, we just want to do the computation stored on the program and save the values back to a buffer that will be used later to paint the geometry.
An example of this approach is the WebGL2Particles demo by @toji
The key point here is that we're performing first the computation using a specific shader and we use these computed attributes to render the geometry using a https://github.com/toji/webgl2-particles-2/blob/gh-pages/index.html#L55-L74 unrelated to the transformfeedback.

  1. The second approach will be to integrate it on the pipeline. So we could have a material definition like:
var materialWithTF = new THREE.ShaderMaterial( {
  uniforms: {...},
  vertexShader: document.getElementById( 'vs' ).textContent,
  fragmentShader: document.getElementById( 'fs' ).textContent
  transformFeedbackVaryings: ['outPosition', 'outVelocity']
});

Or we could use injection points for standard materials (Sorry I don't remember the current state on this @mrdoob @pailhead, but you get the point):

var materialWithTF = new THREE.StandardMaterial( {
  transformFeedbackVaryings: ['outPosition', 'outVelocity'],
  preVertex: 'out vec3 outPosition; out vec3 outVelocity;',
  vertexMain: 'outPosition = position + velocity * delta; outVelocity *= acceleration;',
});

So the renderer and the related modules should take the transformFeedback attributes into account and generate the buffers, doing the pingpong (this could be defined on the material too), binding the tf and the attributes.
With this second approach we don't separate the computation from the actual rendering as we just do it in one pass.
An example of this implementation can be found here on the WebGL2Samples Where with just one drawcall you compute and render at the same time using just one program


  • I'm not sure if there's a huge overhead between option (1) or (2). Although until we won't have multiview support on three.js, (1) will do just one call to compute the new attributes while on (2) we will call twice one per each eye, as the usual drawcalls.
  • I'd like to know if people would like to have the option (1) without rendering anything after, so just to do some gpgpu, or if it's a good idea to have both for two specific use cases.
@pailhead
Copy link
Contributor

pailhead commented Jul 5, 2018

(Sorry I don't remember the current state on this @mrdoob @pailhead, but you get the point):

The latest was here #14231 and the current state is WON'T DO.

Please consult this for alternative implementation #14333.

This might also be worth taking a look at:

https://github.com/pailhead/three-refactor-chunk-material

@mrdoob
Copy link
Owner

mrdoob commented Jul 12, 2018

  1. The second approach will be to integrate it on the pipeline.

This seems nicer. But it depends of how much code it adds.

@pailhead
Copy link
Contributor

@mrdoob how much code is too much code? Are there any guidelines for this?

@yomboprime
Copy link
Collaborator

My opinion is that (1.) is much more versatile. Imagine you have some computations to do which have nothing or nearly nothing to do with what is visually represented.

@fernandojsg
Copy link
Collaborator Author

fernandojsg commented Jul 16, 2018

@yomboprime Yep, I'm currently working on the (1) option having in mind that we could use it to implement (2) to have some syntactic sugar for using it in just one pass.

@munrocket
Copy link
Contributor

Looks like good proposal actually.

@Mugen87
Copy link
Collaborator

Mugen87 commented Jun 11, 2024

Transform feedback is implemented in WebGPURenderer for the WebGL backend when using storage attributes. The new TSL-based API is very versatile and I think it is unrealistic to implement something comparable in WebGLRenderer without significant refactorings.

IMO, it's best for the project to not implement transform feedback in WebGLRenderer but guide devs towards WebGPURenderer if they want this technique in their projects. The following examples use the new compute API of WebGPURenderer. When targeting a WebGL backend (by using Firefox or Safari), transform feedback is used (otherwise compute shaders in WebGPU).

https://threejs.org/examples/webgpu_compute_geometry
https://threejs.org/examples/webgpu_compute_particles
https://threejs.org/examples/webgpu_compute_particles_rain

@mrdoob If you are okay with this proposal, we can close #14503, #26777 and this issue.

@mrdoob
Copy link
Owner

mrdoob commented Jun 11, 2024

@Mugen87 Sounds good 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants