{"action":"created","issue":{"url":"https://api.github.com/repos/mrdoob/three.js/issues/14724","repository_url":"https://api.github.com/repos/mrdoob/three.js","labels_url":"https://api.github.com/repos/mrdoob/three.js/issues/14724/labels{/name}","comments_url":"https://api.github.com/repos/mrdoob/three.js/issues/14724/comments","events_url":"https://api.github.com/repos/mrdoob/three.js/issues/14724/events","html_url":"https://github.com/mrdoob/three.js/issues/14724","id":351260618,"node_id":"MDU6SXNzdWUzNTEyNjA2MTg=","number":14724,"title":"Drawcalls optimization: ordering faces by materialIndex","user":{"login":"jfcampos","id":7152559,"node_id":"MDQ6VXNlcjcxNTI1NTk=","avatar_url":"https://avatars1.githubusercontent.com/u/7152559?v=4","gravatar_id":"","url":"https://api.github.com/users/jfcampos","html_url":"https://github.com/jfcampos","followers_url":"https://api.github.com/users/jfcampos/followers","following_url":"https://api.github.com/users/jfcampos/following{/other_user}","gists_url":"https://api.github.com/users/jfcampos/gists{/gist_id}","starred_url":"https://api.github.com/users/jfcampos/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jfcampos/subscriptions","organizations_url":"https://api.github.com/users/jfcampos/orgs","repos_url":"https://api.github.com/users/jfcampos/repos","events_url":"https://api.github.com/users/jfcampos/events{/privacy}","received_events_url":"https://api.github.com/users/jfcampos/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":3,"created_at":"2018-08-16T15:39:14Z","updated_at":"2018-08-17T08:37:01Z","closed_at":null,"author_association":"NONE","body":"##### Description of the problem\r\n\r\nRecently I managed to greatly improve the performance in one of my scenes and wanted to share my solution, maybe this could end up as a feature in three.js... or maybe it already exists and I just didn't see it :)\r\n\r\nMy 3D model is one big mesh (exported from blender) with over 40 materials, lightmapping, etc, and loading it into my scene adds ~900 drawcalls, resulting in very poor performance (specially in VR).\r\n\r\nSo I had the idea of grouping the faces with the same materialIndex together, hoping they will be drawn in the same drawcall. I created this script and the drawcalls reduced from over 1000 to 95.\r\n\r\nIf this is a valid solution I can do a PR.\r\n\r\n\r\n        var geometry = mesh.geometry;\r\n\r\n        var perMaterial = {};\r\n\r\n        //Categorize faces and uvs by materialIndex\r\n        for (var i = 0; i < geometry.faces.length; i++) {\r\n            var f = geometry.faces[i];\r\n            if (!perMaterial[f.materialIndex]) {\r\n                perMaterial[f.materialIndex] = [];\r\n            }\r\n            var temp = {};\r\n            temp.face = f;\r\n            temp.uvs = [];\r\n            for (var j = 0; j < geometry.faceVertexUvs.length; j++) {\r\n                temp.uvs.push(geometry.faceVertexUvs[j][i]);\r\n            }\r\n\r\n            perMaterial[f.materialIndex].push(temp);\r\n        }\r\n\r\n        //Create new ordered arrays\r\n        var faces = [];\r\n        var uvs = [];\r\n\r\n        for (var key in perMaterial) {\r\n            for (var i = 0; i < perMaterial[key].length; i++) {\r\n                var temp = perMaterial[key][i];\r\n                faces.push(temp.face);\r\n                for (var j = 0; j < temp.uvs.length; j++) {\r\n                    if (!uvs[j]) uvs[j] = [];\r\n                    uvs[j].push(temp.uvs[j]);\r\n                }\r\n            }\r\n        }\r\n\r\n        //Asign new arrays to geometry\r\n        geometry.faces = faces;\r\n\r\n        for (var i = 0; i < uvs.length; i++) {\r\n            geometry.faceVertexUvs[i] = uvs[i];\r\n        }\r\n\r\n        geometry.elementsNeedUpdate = true;\r\n\r\n##### Three.js version\r\n\r\n- [x] Dev\r\n- [ ] r95\r\n- [ ] ...\r\n\r\n##### Browser\r\n\r\n- [x] All of them\r\n- [ ] Chrome\r\n- [ ] Firefox\r\n- [ ] Internet Explorer\r\n\r\n##### OS\r\n\r\n- [x] All of them\r\n- [ ] Windows\r\n- [ ] macOS\r\n- [ ] Linux\r\n- [ ] Android\r\n- [ ] iOS\r\n\r\n##### Hardware Requirements (graphics card, VR Device, ...)\r\n"},"comment":{"url":"https://api.github.com/repos/mrdoob/three.js/issues/comments/413797742","html_url":"https://github.com/mrdoob/three.js/issues/14724#issuecomment-413797742","issue_url":"https://api.github.com/repos/mrdoob/three.js/issues/14724","id":413797742,"node_id":"MDEyOklzc3VlQ29tbWVudDQxMzc5Nzc0Mg==","user":{"login":"Mugen87","id":12612165,"node_id":"MDQ6VXNlcjEyNjEyMTY1","avatar_url":"https://avatars2.githubusercontent.com/u/12612165?v=4","gravatar_id":"","url":"https://api.github.com/users/Mugen87","html_url":"https://github.com/Mugen87","followers_url":"https://api.github.com/users/Mugen87/followers","following_url":"https://api.github.com/users/Mugen87/following{/other_user}","gists_url":"https://api.github.com/users/Mugen87/gists{/gist_id}","starred_url":"https://api.github.com/users/Mugen87/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Mugen87/subscriptions","organizations_url":"https://api.github.com/users/Mugen87/orgs","repos_url":"https://api.github.com/users/Mugen87/repos","events_url":"https://api.github.com/users/Mugen87/events{/privacy}","received_events_url":"https://api.github.com/users/Mugen87/received_events","type":"User","site_admin":false},"created_at":"2018-08-17T08:37:01Z","updated_at":"2018-08-17T08:37:01Z","author_association":"COLLABORATOR","body":"> Is there a reason for not applying this automatically?\r\n\r\nYeah, it would be nice if face sorting is performed automatically by the engine. But from my point of view, it's important that the original geometry object (which is in control of the user) is not altered in an unexpected way. This might be one reason why it's not supported by `three.js`.\r\n\r\nIn any event, it might be a good idea to implement face sorting in `DirectGeometry.fromGeometry()`. This method is internally used by `three.js` when converting a `Geometry` to a `BufferGeometry` object."}}
{"actor":{"display_login":"Mugen87"}}