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

render callback before issuing draw call #7806

Closed
wants to merge 1 commit into from
Closed

render callback before issuing draw call #7806

wants to merge 1 commit into from

Conversation

pailhead
Copy link
Contributor

I find myself doing all sorts of hacks if i want to render special effects using blending modes, depth writes, stencil buffers etc. Would it be useful to have a callback such as this right before the webgl draw call is issued?

For example, i can sequence two meshes by using renderOrder, and then enable stencil testing right before rendering the first one, set the test function before the second one etc.

Id also like to be able to inject a transparent object to be rendered along with the opaque object. Again for special effects, i would like to disable/enable depth tests and writes, draw a few things, then reset the state and go back to rendering the rest of the objects normally.

@mrdoob
Copy link
Owner

mrdoob commented Dec 17, 2015

Do you mind creating an example for illustration purposes? Also, you shouldn't include the builds in the PR.

@pailhead
Copy link
Contributor Author

Pardon, first time doing this. Yes I can muster something up

@pailhead
Copy link
Contributor Author

I didnt have time to come up with a meaningful example, but i did see some other features that were implemented that could also benefit from this.

My usage case would be something like this:

stencil buffer management

sequencing two meshes and a mask to render in a specific order and make use of the stencil buffer which has very little exposure in Three.

var maskMesh = new THREE.Mesh( maskGeom , maskMat );
maskMesh.onWillRender = function(){
  gl.clearStencil( 0 ); 
  gl.clear( gl.STENCIL_BUFFER_BIT );
  gl.stencilFunc( gl.ALWAYS , 1 , 1 );
  gl.stencilOp( gl.REPLACE , gl.REPLACE , gl.REPLACE );
  gl.colorMask( false , false , false , false ); 
  gl.depthMask( false ); 
}.bind(maskMesh);
maskMesh.renderOrder = SomeOrder + 0;


var meshA = new THREE.Mesh( geomA, matA);
meshA.onWillRender = function(){
  gl.depthMask( true ); 
  gl.colorMask( true , true , true , true );
  gl.stencilFunc( gl.EQUAL , 0 , 1 ); 
  gl.stencilOp( gl.KEEP , gl.KEEP , gl.KEEP ); 
}
meshA.renderOrder = someOrder + 1;



var meshB = new THREE.Mesh( geomB , matB);
meshB.onWillRender = function(){
  gl.stencilFunc( gl.EQUAL , 1 , 1 );
}
meshB.renderOrder = someOrder + 2;

configuring a material before each call

Another example would be #7048 , but without the dynamic property and modifications to the renderer.

If there was a callback like this the same could be achieved with:

var sharedMat = new THREE.ShaderMaterial();

var myMesh = new THREE.Mesh( geom , sharedMat );

myMesh.onWillRender = function(){
     this.material.uniforms.myUniform.value = this.customData; 
}.bind(myMesh);

transforming objects that rely on other objects being transformed

var skybox = new THREE.Mesh(...);
var camera = new THREE.Camera();

var controls = new Controls( camera );
   ...

updateLoop(){
  controls.update(); 

 //now i want the skybox to "follow" the camera, ie. has the same position (or relative position) but no rotation

  skybox.position.copy( camera.position);

}

I wish that i could have one Vector3 be a position that many different objects can reference, but three doesnt work like that.

With a callback

skybox.onWillRender = function(){
   this.position.copy( camera.position );
}.bind(skybox);

Although, there should probably be one for rendering, and one for updates, ie. one place where you can setup gl state, object visiblity, and maybe another one - onHasUpdated. And possibly even onHasFinishedRendering or something like that to reset the GL states?

I just slapped this where it felt the most convenient for using the stencil buffer, so im not sure if its in the right place to affect the matrices, but i'll study it some more.

@pailhead
Copy link
Contributor Author

@arose

What do you think of this?

@arose
Copy link
Contributor

arose commented Feb 19, 2016

@pailhead I'll have a look at it on the WE

@pailhead
Copy link
Contributor Author

pailhead commented Sep 22, 2016

@mrdoob

What's the particular reason for this being rejected, only to have the half of it implemented 7 months later? I've desperately been trying to contribute to three, but this is a real turn off :(

Was it the build inclusion, lack of example, something else? I see you changed the wording from Will to Before, but that might be ambiguous, unity and scene kit use will.

@mrdoob
Copy link
Owner

mrdoob commented Sep 22, 2016

This PR didn't get rejected. I basically forgot about it.

I'm a limited human being and it's hard to keep in mind the 146 open PRs. I still don't know what's the best approach for dealing with all this.

But, reading back... Yes, unfortunately I can't easily merge PRs that have conflicts, so the PR got forgotten mainly because the conflicts never got resolved.

@mrdoob
Copy link
Owner

mrdoob commented Sep 22, 2016

#9662

@mrdoob mrdoob closed this Sep 22, 2016
@pailhead
Copy link
Contributor Author

pailhead commented Sep 22, 2016

But, reading back... Yes, unfortunately I can't easily merge PRs that have conflicts, so the PR got forgotten mainly because the conflicts never got resolved.

This didn't have conflicts when it was suggested. It had it now when it went from 75->82. It had exactly zero back then, saving you and everyone time?

So what is one to do in this case? How does one get something like dynamic uniforms pushed, while this can just be forgotten about? Ping more, insist more? I don't want to be pushy, i just want the flexibility, and no bind calls in a loop in the render loop. Also some credit would be nice.

@pailhead pailhead mentioned this pull request Sep 22, 2016
@mrdoob
Copy link
Owner

mrdoob commented Sep 22, 2016

I guess I wasn't too direct myself, but I did ask for the builds to be removed from the PR.

Including the builds is a problem. Maybe at the time it wasn't conflicting but that could have easily lasted 10 minutes. You basically want to create a PR with no conflicts that allows discussion. This PR didn't allow discussion because it had conflicts.

If the issue is that you don't know how to remove the builds from the PR, you could just create new PR without them and close the old one.

@pailhead
Copy link
Contributor Author

Ahh ok, i thought it was something that can easily be skipped on your end. I find myself having to delete my whole repo, fork again, branch, and then do a pull. Been trying to find good tutorials for something like this but i cant :( Once you get past the basic fetch push commit, this thing requires a phd.

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

Successfully merging this pull request may close these issues.

3 participants