- Home /
Rendering with cubes/planes/matrices
Say I have a 3x3x3 cube (so 27 cubes) floating, what would the best way to go at this, memory-saving wise. Would rendering only the visible cubes (in this case.. all but 1, but in others, could be many) help save memory, and how would 1 do that. Also, would it be possible to only render the visible plain of the cube, instead of all 6 sides all the time? Because a 3x3x3 cube would have 162 cube sides, but would only have 54 visible. And if the answer, as I've run across this a few times, resides in a mesh, please link me or explain how to do that as well.
Thanks
- Koder
Answer by Statement · Apr 10, 2011 at 07:47 PM
Yeah, a great help is hiding the cubes that aren't visible (the interior), only displaying the hull cubes. It will greatly improve performance characteristics at the cost of determining which are hull cubes. In a test I did I reduced draw calls from ~1000 to ~500 using this on filled 8x8x8 block.
A more advanced optimization would be to only render the hull faces. To achieve this you need to generate a mesh for the currently visible faces (faces that doesn't have an adjacent cube). In a test I did I reduced draw calls from ~1000 for the naive way to 2 using this on a filled 8x8x8 block.
Finally, you could batch up 8x8x8 cubes into a single mesh for efficient rendering. Depending on your texturing needs you could even try to reduce planar faces, so a big wall becomes just a single quad. It won't reduce draw calls but it can potentially reduce the triangle and vertex counts, yielding faster rendering.
Each of these steps add to the cost of determining visible faces and generating the mesh, so you'd have to balance it for how often you need to build these faces, vs how much speed you really need. I have opted for batching 8x8x8 cubes, generating only visible faces in my own project and it performs well.
I also use an atlas texture so I don't have to do several draw calls because I want a cube to look different from another cube. The statistics window is hard to read but it's reading 57 draw calls and 2433.8 fps. Actually, in this test I think I used 16x16x16 chunks.
for all that, more if I could. First things first, is there a guide on creating these meshes or deter$$anonymous$$ing which are hull/interior cubes anywhere or is this just something I should experiment with? Any suggestions? $$anonymous$$y textures are only 16x16 and I'm not making a $$anonymous$$ecraft clone, so I don't need a huge area with millions and millions of cubes, so just $$anonymous$$or optimization might do it, though the test I ran with around 14k cubes basically lagged me out of commission, so I do still obviously need some optimization.
Well the deter$$anonymous$$ation of the cube hull is pretty easy. For a given cube at x,y,z you just check if there exist a cube at x+1, x-1, y+1, y-1, z+1, z-1 (all 6 sides), and for each side there is no cube, you generate the triangles for that face. You'll need to know how to create meshes procedurally. Check Unity3D website for their procedural tutorial/project to get started. It's a bit complex to write efficient code (like I make use of cache friendly space curves to squeeze out as much performance as I can, but I'm a nerd) but the basics are surprisingly simple.
By the way, for performance geeks and general boasting: 2400 fps is in editor. In a standalone I got about 3500 fps :)
for boasting.. $$anonymous$$idding. I can appreciate solid code ;) Thanks for the help.
Answer by Jordane Almeida · Jul 31, 2012 at 10:43 PM
0 I've got a problem, not yet assimilated how to make the UVs of a cube here is the code can someone help me?
using UnityEngine; using System.Collections;
[RequireComponent (typeof (MeshCollider))] [RequireComponent (typeof (MeshFilter))] [RequireComponent (typeof (MeshRenderer))]
public class Create_Cube : MonoBehaviour {
public Color ColorBloc; public Texture2D Textura;
// Use this for initialization void Start () {
Mesh mesh = new Mesh (); mesh=GetComponent().mesh; Vector3 p0 = new Vector3(0,0,0); Vector3 p1 = new Vector3(1,0,0); Vector3 p2 = new Vector3(0,1,0); Vector3 p3 = new Vector3(0,0,1); Vector3 p4 = new Vector3(1,0,1); Vector3 p5 = new Vector3(1,1,0); Vector3 p6 = new Vector3(0,1,1); Vector3 p7 = new Vector3(1,1,1);
mesh.vertices = new Vector3[]{p0,p1,p2,p3,p4,p5,p6,p7}; mesh.triangles = new int[]{ 0,2,1, 1,2,5, //face 1 3,0,1, 1,4,3, //face 2 0,3,2, 2,3,6, //face 3 1,5,4, 5,7,4, //face 4 6,3,4, 6,4,7, //face 5 6,5,2, 7,5,6 //face 6 };
//mesh.uv = new Vector2[]{new Vector2(0.0f,0.0f),new Vector2(1.0f,0.0f),new Vector2(0.0f,1.0f),new Vector2(0.0f,0.0f),new Vector2(1.0f,0.0f),new Vector2(1.0f,1.0f),new Vector2(0.0f,1.0f),new Vector2(1.0f,1.0f)};
mesh.uv = new Vector2[]{ new Vector2(0,0), new Vector2(0,1),
new Vector2(1,0),new Vector2(0,1),
new Vector2(1,1), new Vector2(0,0),
new Vector2(0,0), new Vector2(1,0)
};
renderer.material = new Material(Shader.Find("Diffuse")); renderer.material.mainTexture = Textura; renderer.material.color = ColorBloc;
mesh.RecalculateNormals(); mesh.RecalculateBounds (); mesh.Optimize();
} // Update is called once per frame void Update () {
} }