{"id":15387011,"url":"https://github.com/gkjohnson/unity-rendering-investigation","last_synced_at":"2025-11-13T22:53:29.828Z","repository":{"id":66338485,"uuid":"101502485","full_name":"gkjohnson/unity-rendering-investigation","owner":"gkjohnson","description":"Investigation into different Unity rendering approaches with an eye on performance","archived":false,"fork":false,"pushed_at":"2017-10-20T02:51:58.000Z","size":41,"stargazers_count":28,"open_issues_count":1,"forks_count":4,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-05-26T22:05:54.432Z","etag":null,"topics":["graphics","performance","procedural","shaders","unity","unity3d"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gkjohnson.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-08-26T17:42:14.000Z","updated_at":"2025-03-29T01:18:06.000Z","dependencies_parsed_at":"2024-03-14T04:47:17.375Z","dependency_job_id":null,"html_url":"https://github.com/gkjohnson/unity-rendering-investigation","commit_stats":{"total_commits":45,"total_committers":1,"mean_commits":45.0,"dds":0.0,"last_synced_commit":"fe2bff4f61a79afb33d1d8a3926caa5953214cf5"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/gkjohnson/unity-rendering-investigation","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gkjohnson%2Funity-rendering-investigation","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gkjohnson%2Funity-rendering-investigation/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gkjohnson%2Funity-rendering-investigation/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gkjohnson%2Funity-rendering-investigation/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gkjohnson","download_url":"https://codeload.github.com/gkjohnson/unity-rendering-investigation/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gkjohnson%2Funity-rendering-investigation/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":284304462,"owners_count":26982161,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-11-13T02:00:06.582Z","response_time":61,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["graphics","performance","procedural","shaders","unity","unity3d"],"created_at":"2024-10-01T14:51:22.038Z","updated_at":"2025-11-13T22:53:29.811Z","avatar_url":"https://github.com/gkjohnson.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# unity-rendering-investigation\n\nA basic performance investigation around a variety of rendering techniques within Unity.\n\n# Approaches\n## Unity Renderer MonoBehaviour\nEvery mesh gets its own _GameObject_, _MeshFilter_, and _Renderer_ components.\n\n## Graphics.DrawMesh API\nTransform matrices and materials are cached and all meshes are drawn using the `Graphics.DrawMesh()` function.\n\n### Details\nNo overhead and management of _Renderers_ and _MeshFilters_.\n\n## Graphics.DrawMesh API with MaterialPropertyBlock\nSame as above, but one material is used and each mesh gets its own _MaterialPropertyBlock_ to augment that material.\n\n### Details\n_MaterialPropertyBlock_ is supposed to be more efficient, but seems to take more time render.\n\nIt's possible that this is just more memory efficient. Results in the same number of set pass calls and batches.\n\n## Graphics.DrawProcedural API\nEach mesh is converted into two _ComputeBuffers_ for both indices and attributes which are referenced in the vertex shader. A material and matrix are cached for each mesh and rendered using the `Graphics.DrawProcedural()` function and `GL.PushMatrix()` to set the transform of the draw.\n\nEach material takes both that \"points\" and \"attributes\" compute buffers as parameters.\n\n### Details\nDespite many draws, the Unity stats window only displays that two \"draw calls\" are being made.\n\nEvery draw requires a new set pass call.\n\nBecause the mesh is procedural this will by-pass all of Unity's internal calculations rendering logic like frustum culling.\n\nAttributes can be stored in custom formats and unpacked in the vertex shader to save on memory.\n\n## Graphics.DrawProcedural API with Unpacked Vertex Buffer\nSame as above, but the attributes for the mesh are unpacked into a single _ComputeBuffer_ with three vertices per triangle.\n\n### Details\nOnly pro might be that there is less array access in the vertex shader.\n\nThis approach takes more memory and transforms more vertices.\n\n## Graphics.DrawProcedural with Visible Triangles Array\nRuns an occlusion pass, counts the triangles, generates an array of visible triangles, and renders only the visible triangles using DrawProcedural.\n\n### Details\nRequires a few compute shader and prepasses to run. These passes can be done over multiple frames:\n- Render whole model to renderTexture\n- Clear the \"visible\" array\n- Mark triangles as \"visible\" in a buffer with a compute shader pass\n- Write the triangle ids needed to an append buffer in a compute shader pass\n\nMore memory is required for the extra textures and buffers.\n\nThis limits the amount of triangles that have to be drawn to the primary buffer every frame to a minimal and possibly consistent count.\n\nMoving a mesh requires updating a buffer with the model attributes.\n\n# Other Concepts\n## Single ComputeBuffer for All Meshes\nOne compute buffer could be used to store all the attributes for all meshes with an offset buffer to help address a specific point in the attribute buffer to render. Multiple meshes could then be drawn by instancing and the instanceId can be used to address the specific mesh to draw.\n\nThe biggest issue is that when using `DrawProcedural()`, you have to specify the amount of vertices, which means every mesh must be the same size.\n\n## Dynamic ComputeBuffer\nDecide which triangles should be drawn and generate the data for the compute buffer that will be drawn.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgkjohnson%2Funity-rendering-investigation","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgkjohnson%2Funity-rendering-investigation","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgkjohnson%2Funity-rendering-investigation/lists"}