{"action":"created","issue":{"url":"https://api.github.com/repos/mrdoob/three.js/issues/10093","repository_url":"https://api.github.com/repos/mrdoob/three.js","labels_url":"https://api.github.com/repos/mrdoob/three.js/issues/10093/labels{/name}","comments_url":"https://api.github.com/repos/mrdoob/three.js/issues/10093/comments","events_url":"https://api.github.com/repos/mrdoob/three.js/issues/10093/events","html_url":"https://github.com/mrdoob/three.js/pull/10093","id":188592394,"number":10093,"title":"Automatic Geometry instancing","user":{"login":"Benjamin-Dobell","id":482276,"avatar_url":"https://avatars.githubusercontent.com/u/482276?v=3","gravatar_id":"","url":"https://api.github.com/users/Benjamin-Dobell","html_url":"https://github.com/Benjamin-Dobell","followers_url":"https://api.github.com/users/Benjamin-Dobell/followers","following_url":"https://api.github.com/users/Benjamin-Dobell/following{/other_user}","gists_url":"https://api.github.com/users/Benjamin-Dobell/gists{/gist_id}","starred_url":"https://api.github.com/users/Benjamin-Dobell/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Benjamin-Dobell/subscriptions","organizations_url":"https://api.github.com/users/Benjamin-Dobell/orgs","repos_url":"https://api.github.com/users/Benjamin-Dobell/repos","events_url":"https://api.github.com/users/Benjamin-Dobell/events{/privacy}","received_events_url":"https://api.github.com/users/Benjamin-Dobell/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":24,"created_at":"2016-11-10T19:10:25Z","updated_at":"2016-11-13T05:57:31Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/mrdoob/three.js/pulls/10093","html_url":"https://github.com/mrdoob/three.js/pull/10093","diff_url":"https://github.com/mrdoob/three.js/pull/10093.diff","patch_url":"https://github.com/mrdoob/three.js/pull/10093.patch"},"body":"When I first started using three.js I read that it supported instancing. It wasn't until I'd been using it for a while that I realised that you were supposed to use `InstancedBufferGeometry` to enable instancing. However, the issue with that is that your instances aren't actually part of the normal scene work-flow, it's pretty complicated for most users.\r\n\r\nThis on the other hand is turned on by default. Geometry will be batched and submitted to the GPU in one go as long as a browser supports the necessary extensions. An \"instancing texture\" is used (world and normal matrices encoded) when floating point vertex-shader accessible textures are available. On systems that don't support this, then the number of available uniforms will be detected and the necessary matrices will be pushed as arrays.\r\n\r\nI've tried to be careful not to break backwards compatibility. The only slight issue will be for those whom are using their own shaders. They'll want to add:\r\n\r\n```\r\n#include <common_vertex>\r\n```\r\n\r\nto the top their vertex shader `main` function. This has been done already for all built-in shaders.\r\n\r\n**EDIT**: ... _unless they're using dynamic uniforms (object render callbacks), in which case the implementation will detect that and won't turn on instancing for that object, so the user will be unaffected._\r\n\r\nInstancing is turned on by default for opaque objects, but off for transparent ones. This is because in-order to effectively batch geometry you don't want to worry about z-sorting. Batching can be enabled for transparent objects if desired.\r\n\r\nPerformance can be tweaked by increasing the instancing texture size (`setInstancingTextureSize( size )`. By default it's 64x64, which gives you batches of size 585. Bumping it to 128x128 will use ever so slightly more VRAM, but will allow for 2340 instances per batch.\r\n\r\nThe increased VRAM is pretty negligible, but pushing a larger texture can itself be less performant than a smaller one if most of your geometry only has a few instances. For this reason, there's `minInstancingBatchSize` which will cause geometry to be rendered without batching (no texture pushing) if there's less than `minInstancingBatchSize` instances viewable in a given frame.\r\n\r\nThese properties can be changed safely between rendering frames if desired.\r\n\r\nSensible defaults have been chosen.\r\n\r\nOf course, instancing can be disabled altogether by setting `autoInstancing` to `false`."},"comment":{"url":"https://api.github.com/repos/mrdoob/three.js/issues/comments/260168702","html_url":"https://github.com/mrdoob/three.js/pull/10093#issuecomment-260168702","issue_url":"https://api.github.com/repos/mrdoob/three.js/issues/10093","id":260168702,"user":{"login":"pailhead","id":4681282,"avatar_url":"https://avatars.githubusercontent.com/u/4681282?v=3","gravatar_id":"","url":"https://api.github.com/users/pailhead","html_url":"https://github.com/pailhead","followers_url":"https://api.github.com/users/pailhead/followers","following_url":"https://api.github.com/users/pailhead/following{/other_user}","gists_url":"https://api.github.com/users/pailhead/gists{/gist_id}","starred_url":"https://api.github.com/users/pailhead/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pailhead/subscriptions","organizations_url":"https://api.github.com/users/pailhead/orgs","repos_url":"https://api.github.com/users/pailhead/repos","events_url":"https://api.github.com/users/pailhead/events{/privacy}","received_events_url":"https://api.github.com/users/pailhead/received_events","type":"User","site_admin":false},"created_at":"2016-11-13T05:57:31Z","updated_at":"2016-11-13T05:57:31Z","body":"Hi,\r\n\r\ni hope i didnt come off as too adversarial. This is all a learning experience for me, and i'm trying to consolidate bits and pieces of the knowledge acquired so far.\r\n\r\nI think you may give too much credit / have a different understanding of the scene graph. Not entirely sure if draw call batching has much to do with it. The simplest example coming to mind being that there can be empty nodes in that graph, not really rendering but just handling transformation. I think it's primary purpose is that, linking nodes together, managing transformations. \r\n\r\nI actually dont know how much optimization happens under the hood of threejs, especially since i missed a few versions, and i can claim limited knowledge of webgl.\r\n\r\n Draw calls can be optimized without actually reducing them right? For example, if the same geometry is being rendered with different materials it's good to have those calls happen consecutively? Also if it's the same material binding different textures, the less state changes between the calls the better?\r\n\r\nAnother thing that might be consider is overdraw, although im a bit fuzzy on this topic. Say you want to cull nodes in some other way without actually drawing them, you then don't want to have them tied up in this batch?\r\n\r\nDoes the size of the mesh matter? Do the nodes transform, if so, is there a trade off - does the shader need to do the texture lookups and **unpacking** if the meshes are static? \r\n\r\n\r\nI'm concerned mostly because you mention dynamic uniforms which i thought got nuked, and you only mention particle effects when it comes to instancing, while the box example up there is a perfectly legitimate use case. \r\n\r\nIf i understand correctly, you want to treat the scene as if it contains these 9144 boxes as nodes, but have the renderer automagically batch them. But why? If you are procedurally generating these it's trivial to use proper instancing (with attributes), if you load it baked as one mesh it's also going to be relatively optimized, at the cost of consuming more memory, and a longer load time. In this case i'd also say it's an optimization that you can take care yourself, ie. reduce memory and load time. If you load it from something describing the graph (9144 nodes, 1 geometry) then yes, it would be nice to not have this tank the renderer, and for some optimization to happen under the hood, but still would be very easy to optimize this yourself with the existing tools. I'd still favor extending the tools, than hard coding this. \r\n\r\n\r\nSo as opposed to @mrdoob solution above, where you \"build\" this instanced struct:\r\n\r\n    var mySceneGraph = Loader.load( 'collada.dae' ); //obtain something somehow with a bunch of nodes, sharing geometry\r\n    var myOptimizedStruct = new THREE.MeshGroup( mySceneGraph ); //analyze it and come up with something thats easier to render\r\n\r\n\r\n"}}
{"actor":{"display_login":"pailhead"}}