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
made 'setProgram' and 'loadUniformsGeneric' public methods #6021
Conversation
Looks good to me! |
Of course, I will think of something. |
Added an example that patches the http://arose.github.io/demo/public-renderer-methods/examples/webgl_interactive_instances_gpu.html |
You are using
Your highlight box seems to be unusually large. Could it be an illusion? // I am not seeing the compelling benefit of this PR in this example -- I am not saying it is not there, just that I do not see it. The example has 2000 draw calls in a static scene. Can you please explain what you would have had to do differently if the features of this PR were not available to you? |
Changed the example [1] so that one can compare the 'single material' vs the 'one material per instance' approach. This PR makes it possible to use a single material for multiple geometry instances while allowing to change the material's uniforms on a per instance basis. The updated examples allows setting the number of geometry instances drawn and disabling the 'single material' approach. Notice that initialization is about twice as fast or faster for the 'single material' approach. You may open the browser's developer console to see some stats. Thanks for the suggestions @WestLangley!
Yeah, it often looks quite big because of rather "spike" form of the model. Made it nonetheless a bit smaller and fixed the transparency so that front and back are always visible.
Basically, just use a separate material for each instance, which I added to the example for comparison. [1] http://arose.github.io/demo/public-renderer-methods/examples/webgl_interactive_instances_gpu.html |
One thing I haven't yet incorporated in the example is adding a new transformation matrix uniform. For example the Just to be clear, I think this PR allows you to do potentially brittle things (and the example is not free from that) and I would very much like to see an API that allows for object-specific uniforms. However I don't know if there is enough demand and also not how such an API should look like. Maybe it is just too specific and exposing some more internals of |
Demo is much improved. Thanks!
Maybe it is best not to do that here. I think what you have is complicated enough. : - )
Agreed. Hence I am on the fence about this one. Another approach may be to allow for user-specified callbacks -- rather than exposing internals. It is a subtle difference, I know. |
I guess such a callback could better communicate why it is there compared to just exposing internals. The following function could be used to implement such a callback. It would need to be called in renderBuffer, renderBufferDirect and renderImmediateObject, just after setProgram is called.. function callPreRenderCallback( camera, lights, fog, material, object ){
if( object.preRenderCallback ){
object.preRenderCallback( camera, lights, fog, material );
}
} Alternatively, the callback could be a method of function callPreRenderCallback( camera, lights, fog, material, object ){
if( _this.preRenderCallback ){
_this.preRenderCallback( camera, lights, fog, material, object );
}
} Not sure about the naming, though. Let's wait what @mrdoob has to say. |
Yeah. I'm not sure this is good. A callback could be nicer but I worry about performance regressions... For this specific use case, would it help if |
I think we are in need of something very similar (extend setProgram from a custom renderer) and in our case it's not just a matter of adding something else that would have to happen after setProgram is called (the callback approach) but more a matter of replacing some of the internal setProgram logic itself so I'd +1 the original proposal from @arose. |
So if there is function refreshUniformsCommon ( uniforms, material, object ) {
// [...]
if( object.color ){
uniforms.diffuse.value = object.color;
}else{
uniforms.diffuse.value = material.color;
}
// [...]
} instead of function refreshUniformsCommon ( uniforms, material ) {
// [...]
uniforms.diffuse.value = material.color;
// [...]
} This would work for my GPU picking use case. A more general approach to object-specific uniform values could be a For my other use case I need the I could prepare a PR if you think this could be the way to go. |
While my use cases might be solved with more specific changes to the @tarelli If you have the time, why don't you explain your use case in another issue. Maybe there is something valuable that can indeed be added to the three.js library. Anyway, sometimes people don't have the time and just need a way to tinker with the internals (without the need to change the original source). |
I think that allowing a renderable object to override any of its material's uniforms would be an excellent enhancement. |
Sorry for the delay, been very busy, here is an example for what we are doing: https://github.com/openworm/org.wormsim.frontend/blob/development/src/main/webapp/js/components/dev/customrenderer/AnimationCustomRenderer.js#L4521. As another point I have found something that I don't understand.If I modify the file three.js itself replacing WebGLRenderer with our version I get 50fps for a given scene. If I replace the renderer later on (still before there is any renderer initialised) just reassigning Update |
I intend to look at this after the refactoring of WebGLRenderer slows down. |
Do you mind giving another go? I think I'm done refactoring... 😅 |
@mrdoob I tried another approach in #7048 -- the code is much less intrusive than in #6150. @tarelli Is it correct that you basically replace In your code you replaced
with
Is it necessary to have this code inside the render loop? Don't you have access to HTH Alexander |
Changed
setProgram
andloadUniformsGeneric
inWebGLRenderer
so that they are public method and accessible from the outside. The goal is to be able to inject code during the object rendering phase, specifically just after or before the WebGL program is set. This allows, for instance, additional transformation matrices likemodelViewMatrixInverse
that depend on data from the to-be-rendered object without reverting to per-object materials. Please see #6010 for a discussion. Also see #5208 for another example where methods ofWebGLRenderer
were made public to allow for custom code. Thanks for considering this.