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

Use external VBO #11883

Closed
4 tasks done
raub opened this issue Aug 3, 2017 · 10 comments
Closed
4 tasks done

Use external VBO #11883

raub opened this issue Aug 3, 2017 · 10 comments

Comments

@raub
Copy link
Contributor

raub commented Aug 3, 2017

Hello!
This is a feature request. I want to be able to optionally feed my VBO to three.js BufferAttribute. I walked through some (three.js) code and couldn't find any way to do so (from outside).

In previous versions of three.js I was able to hack into renderer.properties to replace VBO with my custom one. However, after an upgrade to r86 three's VBO are stored in WebGLAttributes module which is not exposed. Since now the storage is hidden from the outside, I can no longer hack into it from my external codes. Therefore I want to legalize such behavior, to prevent further struggles and hacks.

An example of what I might do with it is following:

	const geo = new THREE.BufferGeometry();
	geo.setDrawRange( 0, REAL_SIZE );
	// ...
	const ba = new THREE.BufferAttribute(_dummyArray, 3);
	ba.count = REAL_SIZE * 3;
	geo.setDrawRange( 0, REAL_SIZE );

	// HERE! set buffer-creator callback
	ba.onCreateCallback = function () {
		// I create it just for example, actually it can come from other lib
		const vertices = [];
		for ( i = 0; i < REAL_SIZE; i ++ ) {
			vertices.push( Math.random() * 2000 - 1000 );
			vertices.push( Math.random() * 2000 - 1000 );
			vertices.push( Math.random() * 2000 - 1000 );
		}
		const vbo = gl.createBuffer();
		gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
		gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
		// Return back to three.js
		return vbo;
	};

	geo.addAttribute('position', ba);
	// ...
	particles = new THREE.Points( geo, materials[0] );
	scene.add( particles );

More of it you can see here.

To summarize: sometimes you end up with preallocated GL buffer and a lack of an ability to use it in three.js BufferGeometry, where it would fit perflectly.

If it sounds reasonable, then I can also show an example of a patch, that makes the above code work:

		var buffer;

		if (attribute.onCreateCallback) {

			buffer = attribute.onCreateCallback();

		} else {

			buffer = gl.createBuffer();

			gl.bindBuffer( bufferType, buffer );
			gl.bufferData( bufferType, array, usage );

		}

		attribute.onUploadCallback();

Just add the condition to see if there is user-defined buffer-creator callback. In WebGLAttributes.js, that's all I need.

If you want me to give more specific reasons for what I do with my buffers, I'll be glad to answer. I can then create a PR with the above changes, if it makes sense.

Three.js version
  • r86+
Browser
  • All of them
  • Even more than that
OS
  • All of them

Thanks for your time! 😃

@alexahdp
Copy link

alexahdp commented Aug 3, 2017

+1

1 similar comment
@pavel-kudinov
Copy link

+1

@pailhead
Copy link
Contributor

pailhead commented Jan 30, 2018

+∞

@mrdoob
Copy link
Owner

mrdoob commented Feb 1, 2018

Instead of trying to hack BufferAttribute... What about an API like this?

var positions = new THREE.GLBufferAttribute( function ( gl ) {

	const vertices = [];

	for ( i = 0; i < REAL_SIZE; i ++ ) {
		vertices.push( Math.random() * 2000 - 1000 );
		vertices.push( Math.random() * 2000 - 1000 );
		vertices.push( Math.random() * 2000 - 1000 );
	}

	const vbo = gl.createBuffer();
	gl.bindBuffer( gl.ARRAY_BUFFER, vbo );
	gl.bufferData( gl.ARRAY_BUFFER, new Float32Array( vertices ), gl.STATIC_DRAW );
	return vbo;

} );
geometry.addAttribute( 'position', positions );

@raub
Copy link
Contributor Author

raub commented Feb 2, 2018

Ofcourse that would also do the trick. Even var positions = new THREE.GLBufferAttribute(vbo) actually would.

There is one more thing to consider here. WebGL2 is comming (and it already works, sometimes). So GLBufferAttribute could be implemented in such a way to allow changing VBO on flight. See this demo.

This whole feature request is really into GPGPU, be it on Node.js or in browser. Most of the usecases require tackling with VBO here and there. Because no one wants to pass tens to hundreds of megabytes between host and device each frame...

Being available as a property of GLBufferAttribute could be really handy. Then just positions.vbo = anotherVbo, or an external call to gl.bindBuffer( gl.ARRAY_BUFFER, positions.vbo ); from outside of the GLBufferAttribute class implementation.

@mrdoob
Copy link
Owner

mrdoob commented Feb 6, 2018

Success! Would you like to do a PR adding GLBufferAttribute?

@raub
Copy link
Contributor Author

raub commented Feb 7, 2018

I'd like to. But as I started thinking of it now, I understood that I don't have the full picture.

  1. What will actually WebGLAttributes do, when it has to deal with GLBufferAttribute? Specifically in that very hack-place of 152c85f, which is invoked from WebGLAttributes.update...

  2. Should GLBufferAttribute subclass BufferAttribute? And how it should behave in all the interactions previously occupied by the usual BufferAttribute? (there probably are some which I don't even know of)

  3. Is there a problem switching VBO back and forth within GLBufferAttribute? I can't predict if three.js has some caching for that matter.

My guess would be: subclass BufferAttribute and tweak WebGLAttributes to account for it, and then just try and see if it works (a bit slippery).

@mrdoob
Copy link
Owner

mrdoob commented Feb 8, 2018

My guess would be: subclass BufferAttribute and tweak WebGLAttributes to account for it, and then just try and see if it works (a bit slippery).

Yep! Sounds like a good start.

@mrdoob mrdoob added this to the rXX milestone Feb 8, 2018
@raub
Copy link
Contributor Author

raub commented Feb 10, 2018

@mrdoob Come see the #13196, it kinda works. I've created (mostly copy-pasted) a separate example for it. Need further advice.

@Mugen87
Copy link
Collaborator

Mugen87 commented Dec 17, 2020

Solved via #13196.

@Mugen87 Mugen87 closed this as completed Dec 17, 2020
@Mugen87 Mugen87 removed this from the rXXX milestone Dec 17, 2020
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

6 participants