Exposing internals + onProject, onRender and onRenderShadow
See original GitHub issueThese 3 simple callbacks + exposing some internal renderer objects allow to implement a set of new fundamental features. The callbacks are for the Object3D class.
onProject
To override the culling routine, i made a spatial index “IndexedVolume” based on Object3D. By returning false in this callback THREE cancels the current projectObject call, the IndexedVolume will perform indexed hierarchical culling and then push the visible objects into the renderList, but projectObject can be called as well to let THREE take over again, furthermore i implemented auto-instancing, impostors and other in this routine.
Asides of custom culling implementations this can be used to render additional objects that aren’t part of the scene hierarchy. Also a module based selection, having render objects in the main scene hierarchy but rendering in a different pass, working as a more flexible version to layers.
The onProject callback receives renderer, camera, frustum, renderList, groupOrder, sortObjects
.
onRender
ImmediateRenderObject is nice but very limited, only allowing triangle mode and a specific set of attributes. onRender allows to implement a custom render call to renderBufferDirect and using + updating any geometries or other operations only possible at this stage, but not with onBeforeRender. It basically also works as ImmediateRenderObject but both gl buffers or THREE managed BufferGeometry can be used, but without being limited to the renderBufferImmediate imlementation.
I replaced isImmediateRenderObject, with isCustomRenderObject , but could be as well a else if case of course.
onRenderShadow
Basically like onProject but for shadows, receiving renderer, camera, frustum, shadowCamera, light, type, scope
and returns if onRenderShadow returns false. It would be nice if any needed methods such as getDepthMaterial could be exposed as well, as it gives much more control to replace renderObject with a modified approach as shadow proxies might be used or a different depth materials management.
Internals
There are some internal objects such as frustum, textures, geometries, properties, objects
that are as well private yet, i needed those for various cases in those callbacks, but especially for onRender. Regarding methods: in WebGLRenderer projectObject, setProgram as well as in WebGLShadowMap renderObject, i called the shadowMap callback version onRenderShadow.
These additions all together would be just a few lines but opening a vast amount of possibilities and more control, it would be great if they could find their way officially into the core.
Additional note: instead calling empty callbacks like onBeforeRender i implemented those as the following, declaring them on the prototype with null:
if ( object.onProject instanceof Function && object.onProject( ... ) === false ) return;
Issue Analytics
- State:
- Created 3 years ago
- Reactions:2
- Comments:14 (5 by maintainers)
Top GitHub Comments
The mentioned internals make a lot sense to use outside as they are needed in a lot cases to make use of those callbacks, some internals make only sense internally, the mentioned ones really give most of control you could need. But there sure are more that would be reasonable to expose, i don’t see a reason to keep them hidden honestly.
There would be one other callback that would be really helpful as well, i currently implemented it as a monkey patch plugin: https://discourse.threejs.org/t/chainable-onbeforecompile-uniforms-per-mesh/8905 (the uniforms per mesh part)
There is almost no project i don’t need it, for some cases having uniform values stored on object/mesh level (or anywhere you need), so you can use 1 material instance for multiple objects, but use different uniform values per object/render call, without having to clone entire materials just for 1 different uniform. I currently implemented it through onBeforeRender which is okay as not always needed and not blocking it, but it would be better at the actual setup, to be implemented on the material class prototype or on the renderer.
I did some tests though i forgot console gives different results than actual scripts. However the difference there was interesting, instanceof performed in chrome couple hundred times faster than null test or empty call. Otherwise a empty call often is faster but sometimes equal, that’s a really odd js quirk.
Those already give most control of the render routine (like the examples i mentioned) in a flexible component way without internal changes.
Yes especially for exposing internals there are many objects that would make it much more flexible if they were public.