Search Unity

After playing minecraft...

Discussion in 'General Discussion' started by jc_lvngstn, Oct 8, 2010.

Thread Status:
Not open for further replies.
  1. DaneC020

    DaneC020

    Joined:
    Mar 19, 2010
    Posts:
    191
    Has anybody looked at Voxel Farm lately? Looks like they are making an affordable indie price and now supports Unity. Thought it was interesting how affordable the engine is now becoming for those who want a solid solution. I am curious to see how the performance is when being used with Unity and not its own rendering engine.



    Anyhow, thought some people who missed this would appreciate a post. :) Continue discussing voxels!
     
    Tethys and GibTreaty like this.
  2. 12pt

    12pt

    Joined:
    May 22, 2013
    Posts:
    20
    Hey everyone, I just took my voxel framework repository and made it public. This code is similar to what I've covered in my voxel tutorial series but with some changes and additions: I've added AO, there's pathfinding code in there (but no examples yet), and the start of some lighting code. I'm hoping this will be a good learning resource for people getting started or stuck on the implementation of something, I'll be adding mode helpful comments over time to help with this.

    http://alexstv.github.io/Voxelmetric/

    It's not the most efficient or best organized project but I'd like to make into a useful resource/framework. Feel free to clone/fork/pull request!

    As a side note I've been working on implementing lighting and I understand the basics but cant seem to speed it up enough for actual use. I'm using a recursive method to propagate light and a byte in the air blocks to store the light value. Does anyone have any tips for speeding up lighting?
    This is the class I'm using right now: https://github.com/AlexSTV/Voxelmetric/blob/master/Assets/Code/Utilities/BlockLight.cs I'm using Reset light to set the light values to 0 or max depending or exposure to sunlight and flood light to iterate over every air block and call spill light to recursively spread light into the neighbours.
     
    mgear and GibTreaty like this.
  3. GibTreaty

    GibTreaty

    Joined:
    Aug 25, 2010
    Posts:
    792
    O_O It's so quick. So smooth. Must inspect.
     
  4. KiwyVoxel

    KiwyVoxel

    Joined:
    Jan 14, 2015
    Posts:
    64
    Hello everyone,

    There is lots of meshing algorythms but most projects that i see seem to tend toward the Boxel one (minecraft like). Is it because people are more fond of it ? Or is it a gameplay consideration, and if so would you like a grid like tooltip for mesh creation ?

    I am looking for upgrading my voxel data structure. Currently it is just a flat array. I hesitate between octree and clipmaps. The latter seem to be the best choice, does someone implement it in Unity 5 ?

    If you want too look at my project, some feedbacks will be greatly apprecieted :
    http://forum.unity3d.com/threads/wip-voxel-meshing.291105/

    12pt Thanks for your tutorials, that's how my project started.
     
  5. JasonBricco

    JasonBricco

    Joined:
    Jul 15, 2013
    Posts:
    956
    Hey guys, quick question about 3D noise.

    All this time I've been using a 2D heightmap for terrain, while I've been working on other features. Now I'm going to start trying to bump it up to 3D.

    Here's the question: what's the best way to do it?

    Should I generate a 2D heightmap like before, but when building up to that height, use 3D noise values to determine which blocks should be placed?

    Or, is there a way to use entirely 3D? But how would you stop it at some point, so it doesn't go to the height limit?

    Thanks!

    PS: Likely was discussed in this gigantic topic, but I haven't had the time to read through all of it yet... it's quite a task.
     
  6. KiwyVoxel

    KiwyVoxel

    Joined:
    Jan 14, 2015
    Posts:
    64
    You should first think to how you want your ground to look like.
    Noise function give interesting result but you can often see the repetitive nature of those functions. On an other hand height maps gives you access to realistics shapes, you can even get access to true geographics readings.
    You could associated both, but keep in mind that can be resource demanding.

    There is a lot to read on the subject, and the Procedural World blog is a really good source of information. Like height maps, wang tiling, densities functions etc...


    You can combine multiple densities functions to represent one mesh with different materials. You can for exemple create a shape that represents the difference between solid ground and air, and combine it with a noise function that represent rocks. You may want to look at Constructive Solid Geometry and boolean algebra to have a proper idee.


    I am not sure what you mean by entirely 3D. Height Map can be 3d value, but cannot represent more than one value for each x and z couple, so only one change between in and out the mesh.
    If you understand the concept of density function you can easily restrict the size of your ground to a percentage of your world's maximum height.

    I hope it is helping you.
     
    Last edited: May 17, 2015
    JasonBricco likes this.
  7. CorWilson

    CorWilson

    Joined:
    Oct 3, 2012
    Posts:
    95
    Yo, 12pt. From what I remember someone saying in this thread, a linked forum made it so that instead of refreshing all the lights when a chunk is updated, they only update all light in a chunksize*2 diameter around the updated block. It pulls down all the light from the top most y of this cubic space. This is in case there's sunlight so it can shoot it down. Otherwise, all light in this area is set to zero and then all light sources within have their light propogation refreshed.

    This way, the refresh iterations are smaller. Otherwise, to speed up any light processing, just multithread it. You should be using multithreading regardless if you haven't implemented it.
     
  8. CommanderFoo

    CommanderFoo

    Joined:
    Jan 10, 2012
    Posts:
    3
    Hey,

    Just want to say thanks to all the info, code, and projects people have shared. I've really learnt a lot reading this topic, and decided to join in.

    I do have some questions, but will just ask 1 for now that is bugging me.

    I've managed to get the greedy algorithm working. Previously I was just culling faces. My problem is, I don't understand how to merge the two together.

    Here is how things are done to give you an idea of the structure;

    World has a dictionary (Vector3 (x, y, z), Chunk) that holds the chunks (16 x 16 x 16). Each chunk has a blocks array to keep record of the blocks in that chunk. Once all the chunks have been created with their blocks set (i.e Air, Stone), I then start the mesh generation. I loop over each chunk and create the mesh.

    I have 2 methods currently, 1 for culling, and 1 for greedy, at the moment only 1 is used as I don't know how to merge them.

    For the culling method, I loop over all the blocks in that chunk, if a face needs to be rendered (i.e north face), I then tell the block renderer to build the face.

    For the greedy method, I use the algorithm by Mikola Lysenko (http://0fps.net/2012/06/30/meshing-in-a-minecraft-game/), this seems to be working well.

    Hopefully someone could give me some tips :)
     
  9. KiwyVoxel

    KiwyVoxel

    Joined:
    Jan 14, 2015
    Posts:
    64
    I am not sur it is really worth it to combine both algorithm. Both in terms of cpu usage and code complexity.

    I guess it really depend on what you are trying to achieve.
    If you are looking for a minecraft like game the culled algorithm (or kind of) is enough, and you should think to the rest of the game that may take more time (chunk management, data structure, shaders, etc...).
    If you really want to use both algorithme. First you cant used both on the same mesh, so you probably need to use the seconde one when your cpu is free (as mentioned in the blog). You probably detect this in your chunk manager, when there is no chunk's mesh to quickly make or remake.
     
  10. JasonBricco

    JasonBricco

    Joined:
    Jul 15, 2013
    Posts:
    956
    So, having some trouble understanding how to use Trilinear Interpolation. I'm using the same method that was posted on the last page:

    Code (CSharp):
    1. public static double TriLerp(float x, float y, float z,
    2.                              double q000, double q001, double q010,
    3.                              double q011, double q100, double q101,
    4.                              double q110, double q111,
    5.                              float x1, float x2,
    6.                              float y1, float y2,
    7.                              float z1, float z2)
    8. {
    9.     double x00 = Lerp(x, x1, x2, q000, q100);
    10.     double x10 = Lerp(x, x1, x2, q010, q110);
    11.     double x01 = Lerp(x, x1, x2, q001, q101);
    12.     double x11 = Lerp(x, x1, x2, q011, q111);
    13.     double r0 = Lerp(y, y1, y2, x00, x01);
    14.     double r1 = Lerp(y, y1, y2, x10, x11);
    15.    
    16.     return Lerp(z, z1, z2, r0, r1);
    17. }
    I saw @RuinsOfFeyrin say the following:

    What are these pre-sampled points, exactly? I figure lower and upper bounds would be 0 to chunk size - 1. 0 to 15 or in my case, 0 to 31.

    Not sure what the pre-sampled points are. Is this the result of noise calculations at the 8 chunk corners? Or are these corners of something else? My attempt at putting in chunk corners resulted in terribly messed up terrain, so I'm assuming that's incorrect.

    Really can't find much using a Google search on this.
     
  11. Noojuno

    Noojuno

    Joined:
    May 25, 2015
    Posts:
    1
    I've been working on my voxel game for a while now and was wondering how you guys handled threads.

    I haven't yet gone back to find the thread discussion from earlier, however I will do that soon.

    My questions are:
    What tasks do you actually thread? I can see terraingen being threaded but I'm unsure about anything else.

    How do you manage the threads you have? How many do you have running at once?
     
  12. KiwyVoxel

    KiwyVoxel

    Joined:
    Jan 14, 2015
    Posts:
    64
    I do not use multiple threads because Unity is not thread safe, i use coroutines. But you can find some interesting discussions few pages back. Someone said that you can make a thread for what you want as long as you do not call Unity functions. I read multiple post where people use anotner thread for mesh calculations.
     
  13. JasonBricco

    JasonBricco

    Joined:
    Jul 15, 2013
    Posts:
    956
    I do terrain noise calculations in two threads and mesh calculations in another thread - you can do this as long as you send the final calculated mesh data to unity in the main thread.

    I use queues. The threads watch the queues for work to do and run it when work enters the queue.

    However, I free the terrain threads back to the OS after my world is generated. Unlike many people here, I am not doing infinite terrain as the design of my game doesn't warrant it.
     
  14. 12pt

    12pt

    Joined:
    May 22, 2013
    Posts:
    20
    I just implemented threading because I think I'm starting to push what you can comfortably do in a frame in one thread. I used threading on the terrain generation, building mesh data and calculating lighting. I'm doing this initially as a prototype to keep developing because I'm not sure about the stability of it but so far I am getting a massive performance boost. I'm managing the threads mostly be setting flags on the chunk to say that it's busy generating a mesh or that the terrain is generated or is in progress, then check the flags before doing anything that relies on them.

    My chunk creation thread starts by instantiating all the chunks and generating the terrain data. Meanwhile it starts a thread to prepare the chunk but it waits until the generation is done for the chunk being created and all the neighbour chunks, then it sets the chunk as busy, builds the mesh and sets a flag saying the mesh is ready and on the next frame the chunk applies the generated mesh.

    Also with threading I got the lighting to run fast enough to update it whenever a chunk changes but I still haven't gotten it to calculate lighting on the chunk's first load.

    I committed these changes to the master branch in my project: https://github.com/AlexSTV/Voxelmetric
     
    GibTreaty likes this.
  15. CorWilson

    CorWilson

    Joined:
    Oct 3, 2012
    Posts:
    95
    I always like your simple solutions, while others would get more complicated with WaitHandles.

    In fact, you used the same thing I did. I basically made a class to represent mesh data and send it to the chunk when it's done in a thread.
     
  16. Silly_Rollo

    Silly_Rollo

    Joined:
    Dec 21, 2012
    Posts:
    501
    What's the smart way to 'seal' a marching cube mesh? If you are zipping through your voxels the ones at the edges if they have density won't generate an intersection point since where they should intersect with negative density is outside your consideration.

    The brute force method is just to loop through more space then your voxels occupy throwing dummy negative voxels at those extra empty spaces and seal the mesh but that's a waste and its causing problems now that I'm chunking since I need to check for extra only when I'm at edges and not when the next chunk over actually has density.

    I'm not trying to do an infinite world by any stretch just some large voxel structures so rather than trying to chunk out to a horizon and not caring what the terrain looks like from other angles I need it to be sealed.
     
  17. Vanamerax

    Vanamerax

    Joined:
    Jan 12, 2012
    Posts:
    938

    What I do, even for an infinite approach, is creating a new density array with +1 dimension on every side (thus +2 dimension on every axis). Then you can fill the edges of this array with the data you want (negative density in order to let the marching cubes seal the mesh). Then you actually fill in this array with the real data like you are used to, but add 1 to every axis in your input coordinate. For example, say I want to apply data from coord (5,3,7) I apply it in this temporary array at coord (6,4,8). This is to account for the extra padding row we introduced in the array (since array index has to start from 0). Now we do the same when getting the data the array in marching cubes, we just add the 1 to the coord. We just loop through the space the data actually occupies, thus adding 1 every time. In marching cubes, we dont have to do explicit bounds checking because of the extra padding row that will keep us covered.

    This all may seem very redundant and time consuming at first, as it seems like a lot more work to do for the cpu. However, what I found was that it was actually faster than doing explicit checks for when we are at an edge.
     
  18. Silly_Rollo

    Silly_Rollo

    Joined:
    Dec 21, 2012
    Posts:
    501
    That makes sense. I'm also trying out surface nets which may be a better fit for my objective but I haven't found a lot of resources on them beyond the 0fps article and a few academic papers. The source code for the 0fps article is pretty dense and not very intuitive. Surface nets as a theory is pretty simple so I'm surprised more haven't attempted it.
     
  19. KiwyVoxel

    KiwyVoxel

    Joined:
    Jan 14, 2015
    Posts:
    64
    The surface nets is an iterative solution, that is why i think most people does not use it in games. 0 fps cheats a bit by using ellipsoidal curve to determine the "best result". But i dont think this is the best method if you are looking for precise and sharp shapes. Dual Contouring (based on marching cubes) are the most used, i think Voxel Farm used it.
     
  20. Silly_Rollo

    Silly_Rollo

    Joined:
    Dec 21, 2012
    Posts:
    501
    DC seems to be overkill for my target. I'd actually like to produce something that looks a bit like Polyworld. MC isn't a great fit since it tends towards such soft shapes so the loss of detail / approximation of surface nets would actually be a benefit. I just don't understand that 0fps code at all. I've never worked with JS but I can usually muddle through any language code but even untangling his for loops is confusing.
     
  21. KiwyVoxel

    KiwyVoxel

    Joined:
    Jan 14, 2015
    Posts:
    64
    Surface nets does not prevent loss of details. At the lower iteration it is similar to a simple Boxel like (minecraft) algorithm. Then the more you iterate the more your shapes are smoothed. But if you dont defined a value at wich to stop (like 0fps and the curve) you will end up with a mostly round shape. To be more precise i strongly encourage you to read the siggraph papers on surfaces nets that make very good explanation.

    If DC is too complicated and MC not sharp enough try to look at Extend MC (EMC is MC but with a better edge splitting method). Also another technique slower but with better meshes the Marching Tetrahedron.

    This might help you :
    http://www.oocities.org/tzukkers/isosurf/isosurfaces.html
     
    Last edited: Jun 12, 2015
  22. RuinsOfFeyrin

    RuinsOfFeyrin

    Joined:
    Feb 22, 2014
    Posts:
    785
    @JasonBricco
    Hey sorry for the late response, been very busy with work which does not leave me much time to get on the computer.

    To answer your question about the pre-sampled points for trilinear interpolation. They are not always the lower and upper bounds of the chunk, but could be in the right circumstances.

    You need to sample the points in a cube. So if the height of your chunks are the same as the width, then you are all good to go. If your height is more, then you need to sample in sections. So for 16x16x128 you actually interpolate 8 cubes vertically of 17x17x17 (yes 17, ill explain why in a second). Make sense?

    Also lets use the chunk at 0,0,0 as an example, with a chunk size of 16x16x128.

    You are sampling the the corners of a cube from 0,0,0 to 16,16,16. Yes 16, not 15. the reason being is you want the interpolation to blend between edges of chunks which this will do.

    Hope that helps.
     
    JasonBricco likes this.
  23. JasonBricco

    JasonBricco

    Joined:
    Jul 15, 2013
    Posts:
    956
    @RuinsOfFeyrin

    Sorry to bother you again - hope you don't mind helping me once more! And also, apologies for the somewhat long post... I finally got back to trying this. And I'm still getting this awful terrain:

    Terrible.jpg

    (Filler prototype textures, not my own)

    Seems these chunks are having difficulty making it through chunk borders, amongst other issues. (The ground terrain is a 2D heightmap terrain).

    I tried to write this in the most simple, dumb way just to see if I could get it to work before refactoring. Here's what I did:

    I have 32x128x32 chunks. So I figured I'd interpolate over four cubes of 32x32x32.

    Each time I go to generate a chunk, I have code that looks like this:

    Code (CSharp):
    1. Vector2i chunkPos = chunk.position;
    2. int chunkX = chunkPos.x * Chunk.Size;
    3. int chunkZ = chunkPos.z * Chunk.Size;
    4.  
    5. currentType.FillNoise1(chunkX, chunkZ);
    6. currentType.FillNoise2(chunkX, chunkZ);
    7. currentType.FillNoise3(chunkX, chunkZ);
    8. currentType.FillNoise4(chunkX, chunkZ);
    This is my attempt at pre-sampling the corners of each of the four cubes. I have some arrays:

    Code (CSharp):
    1. protected double[] noiseCube1 = new double[8];
    2. protected double[] noiseCube2 = new double[8];
    3. protected double[] noiseCube3 = new double[8];
    4. protected double[] noiseCube4 = new double[8];
    These store the pre-sampled points.

    The FillNoise functions look like:

    Code (CSharp):
    1. public void FillNoise1(int chunkX, int chunkZ)
    2. {
    3.     noiseCube1[0] = Simplex.GetMultiNoise3D(6, chunkX, 0, chunkZ, 0.004);
    4.     noiseCube1[1] = Simplex.GetMultiNoise3D(6, chunkX, 32, chunkZ, 0.004);
    5.     noiseCube1[2] = Simplex.GetMultiNoise3D(6, chunkX, 0, chunkZ + Chunk.Size, 0.004);
    6.     noiseCube1[3] = Simplex.GetMultiNoise3D(6, chunkX, 32, chunkZ + Chunk.Size, 0.004);
    7.     noiseCube1[4] = Simplex.GetMultiNoise3D(6, chunkX + Chunk.Size, 0, chunkZ, 0.004);
    8.     noiseCube1[5] = Simplex.GetMultiNoise3D(6, chunkX + Chunk.Size, 32, chunkZ, 0.004);
    9.     noiseCube1[6] = Simplex.GetMultiNoise3D(6, chunkX + Chunk.Size, 0, chunkZ + Chunk.Size, 0.004);
    10.     noiseCube1[7] = Simplex.GetMultiNoise3D(6, chunkX + Chunk.Size, 32, chunkZ + Chunk.Size, 0.004);
    11. }
    The other 3 just use the other noiseCube arrays (with higher Y values). GetMultiNoise3D takes in the parameters: octaves, x, y, z, and frequency.

    And then when I go to generate terrain columns, I have this to get me noise with TriLerp:

    Code (CSharp):
    1. protected double Get3DNoise(int x, int y, int z)
    2. {
    3.     if (y > 96)
    4.     {
    5.         return TerrainUtils.TriLerp(x, y, z, noiseCube4[0], noiseCube4[1], noiseCube4[2], noiseCube4[3], noiseCube4[4],
    6.                                     noiseCube4[5], noiseCube4[6], noiseCube4[7], 0, 31, 0, 31, 0, 31);
    7.     }
    8.     else if (y > 64)
    9.     {
    10.         return TerrainUtils.TriLerp(x, y, z, noiseCube3[0], noiseCube3[1], noiseCube3[2], noiseCube3[3], noiseCube3[4],
    11.                                     noiseCube3[5], noiseCube3[6], noiseCube3[7], 0, 31, 0, 31, 0, 31);
    12.     }
    13.     else if (y > 32)
    14.     {
    15.         return TerrainUtils.TriLerp(x, y, z, noiseCube2[0], noiseCube2[1], noiseCube2[2], noiseCube2[3], noiseCube2[4],
    16.                                     noiseCube2[5], noiseCube2[6], noiseCube2[7], 0, 31, 0, 31, 0, 31);
    17.     }
    18.     else
    19.     {
    20.         return TerrainUtils.TriLerp(x, y, z, noiseCube1[0], noiseCube1[1], noiseCube1[2], noiseCube1[3], noiseCube1[4],
    21.                                     noiseCube1[5], noiseCube1[6], noiseCube1[7], 0, 31, 0, 31, 0, 31);
    22.     }
    23. }
    24.  
    I figure out which section I'm in along the Y and use that to figure out the noiseCube array to pull from.

    I made sure to: 1. fill the arrays in the right corner order: 000, 001, 010, 011, 100, 101, 110, 111 and I also swapped the Y and Z I believe.

    Finally, I just call:

    Code (CSharp):
    1. double noise3D = Get3DNoise(x, y, z);
    Where x, y, and z are in chunk coordinates (0 to 31) into the function I posted above to get the value.

    This code is pretty awful right now. I just wrote it out in the fastest way I could think of to see if I could get it to work, and hope to refactor it once it works.

    Could you point out to me what I'm doing wrong here? Clearly I'm messing something up terribly.

    Thanks!
     
  24. JasonBricco

    JasonBricco

    Joined:
    Jul 15, 2013
    Posts:
    956
    Can anyone tell me what I'm doing wrong with the Trilinear interpolation? I really don't think I learned it well enough.

    I tried:

    1. Using world coordinate values instead of chunk coordinate values for the x, y, z points.
    2. Using world coordinates for the x1, x2, y1, y2, z1, z1 (instead of always 0 to 31, I tried 0 to 31, 32 to 63, etc).
    4. Using 0 to 1 as the bounds (even though as far as I understood it it should be chunk boundaries).

    None of that produced a result even a little closer. I looked up resources on trilinear interpolation, and found very little. And the little I did find did not help me here.
     
  25. RiokuTheSlayer

    RiokuTheSlayer

    Joined:
    Aug 22, 2013
    Posts:
    356
    I haven't read back far enough to know exactly what's up behind your script, but I can say I got an effect like this when dividing my coordinates in the noise as ints, which rounds them to whole numbers. Make sure you're using the input coordinates for the noise as floats if you're doing any math on them so they transition smoothly, and that you're not using the chunk coords without the block coords.
     
  26. RuinsOfFeyrin

    RuinsOfFeyrin

    Joined:
    Feb 22, 2014
    Posts:
    785
    @JasonBricco

    Hey sorry my responses always come way later. My job is traveling construction so during the summer im either working, driving or sleeping with the occasional day off which is when i get on the computer.

    It has been a while since I have done or helped anyone with tri-linear interpolation so im just guessing at the moment but it looks like a problem i have encountered and so did oter people i was helping.

    I want to say the tri-lerp function is expecting Z & Y to be swapped when fed in.

    So sample the points like normal, but then when you tri-lerp a value swap the Z & Y values. I think that should fix it.... I think. Im gonna go look at the conversation I was having with someone else who had a similar issue and see what we determined the fix was for sure, but im almost positive it has something to do with tri-lerp expecting Z to be your vertical axis.
     
  27. JasonBricco

    JasonBricco

    Joined:
    Jul 15, 2013
    Posts:
    956
    I thought I did that...

    Let me see, the order listed in the function was:

    000, 001, 010, 011, 100, 101, 110, 111.

    Swapping Y and Z, you get:

    000, 010, 001, 011, 100, 110, 101, 111.

    And I did:

    Code (CSharp):
    1. public void FillNoise1(int chunkX, int chunkZ)
    2. {
    3.     noiseCube1[0] = Simplex.GetMultiNoise3D(6, chunkX, 0, chunkZ, 0.004); // 000
    4.     noiseCube1[1] = Simplex.GetMultiNoise3D(6, chunkX, 32, chunkZ, 0.004); // 010
    5.     noiseCube1[2] = Simplex.GetMultiNoise3D(6, chunkX, 0, chunkZ + Chunk.Size, 0.004); // 001
    6.     noiseCube1[3] = Simplex.GetMultiNoise3D(6, chunkX, 32, chunkZ + Chunk.Size, 0.004); // 011
    7.     noiseCube1[4] = Simplex.GetMultiNoise3D(6, chunkX + Chunk.Size, 0, chunkZ, 0.004); // 100
    8.     noiseCube1[5] = Simplex.GetMultiNoise3D(6, chunkX + Chunk.Size, 32, chunkZ, 0.004); // 110
    9.     noiseCube1[6] = Simplex.GetMultiNoise3D(6, chunkX + Chunk.Size, 0, chunkZ + Chunk.Size, 0.004); // 101
    10.     noiseCube1[7] = Simplex.GetMultiNoise3D(6, chunkX + Chunk.Size, 32, chunkZ + Chunk.Size, 0.004); // 111
    11. }
    Seems I did, unless I made some stupid mistake...
     
  28. RuinsOfFeyrin

    RuinsOfFeyrin

    Joined:
    Feb 22, 2014
    Posts:
    785
    @JasonBricco

    Hey, so i went back to look at my code so I could copy the relevant section.

    Code (CSharp):
    1. float xyz000 = GetBlockValue( wX , wZ, wY);
    2. float xyz001 = GetBlockValue( wX , wZ, (wY + triLerpMax));
    3. float xyz101 = GetBlockValue( (wX + triLerpMax), wZ, (wY + triLerpMax));
    4. float xyz100 = GetBlockValue( (wX + triLerpMax), wZ, wY);
    5. float xyz010 = GetBlockValue( wX, (wZ + triLerpMax), wY);
    6. float xyz011 = GetBlockValue( wX, (wZ + triLerpMax), (wY + triLerpMax));
    7. float xyz111 = GetBlockValue( ( wX + triLerpMax), (wZ + triLerpMax), (wY +triLerpMax));
    8. float xyz110 = GetBlockValue( ( wX + triLerpMax), (wZ + triLerpMax), wY);
    and then the tri-lerp
    Code (CSharp):
    1. TERRAIN_GENERATOR.triLerp (iX,iY,iZ, xyz000,xyz001,xyz010,xyz011,xyz100,xyz101,xyz110,xyz111, x, (x+triLerpMax),y,(y+triLerpMax),z,(z+triLerpMax));

    So hopefully the code can explain it a bit easier.
    You maintain the order of the corner values themselves, just when you are getting the noise for a block (my getBlockValue) you swap the y and z values. This is because the tri-lerp function is expecting a different vertical axis, and the way the math works it goes all wonky.
     
  29. RiokuTheSlayer

    RiokuTheSlayer

    Joined:
    Aug 22, 2013
    Posts:
    356
    http://www.mediafire.com/download/dg3h3rg862j1n9h/Rio's+Voxel+Game.zip#39;s_Voxel_Game.zip

    If anyone would like to look at what I've been working on, here ya go. It's a few weeks in progress.

    It's got all the basic voxel engine features, like "infinite" terrain, breaking/placing blocks, and some basic inventory work.

    It's much less intense than minecraft, and it's got a few cool things that you can't see yet.

    I wanted to mention a few things.

    First, the terrain "Loops" up and down. If you fall all the way down out of the world, after a few seconds of falling you'll fall back to the top of the world. I did this because the caves slowly get larger as you decend, to the point where you only get caves, no terrain at all. That point is about -2K y. At that point, it teleports you to 1k y, and the terrain starts about 15y, but you fall at a decent enough speed to reach it in a reasonable amount of time.

    Second, the world is not actually textured. It uses a seperate Perlin Noise shader that just rounds it out to the coordinates of the block. That makes it look better than all being exactly the same color, but doesn't really do very much preformance wise.

    Third, I use multithreading for three things. Loading the area around the player, Generating meshes and generating terrain data. Loading areas is a thing that Minecraft itself does, but I don't know about meshgeneration and data generation. But using multithreading really boosts performance. Of course, you need to actually have a computer that can use multithreading, but, still.

    And last, I used a few assets off of the store for this. First, I used SESSAO, Sonic Ether's Screen Space Ambient Occlusion. It works really well, and with nearly no performance impact, I see no reason to switch to static AO on the mesh. The other asset I used was Easy Noise Generator, because Unity's Perlin Noise wasn't cutting it.

    With all that said, enjoy! I'd be happy to share about things behind the game if anyone has any questions.
     
  30. RuinsOfFeyrin

    RuinsOfFeyrin

    Joined:
    Feb 22, 2014
    Posts:
    785
    @RiokuTheSlayer

    Hey so I took a minute to download the project you have been working on.

    First, let me say that it looks pretty good from what I could see. The terrain looked nice, and i liked the color variation to the blocks.

    However I couldn't see much more then where I started, or do much of anything because the game was very choppy to me. I'm sure this was in part because the system i was testing it on is an older system though. I was able to after a few minutes master the choppiness and move some so I could see new terrain load.

    Also when i would jump i would jump very high. I was not sure if this was working as intended, or a by product of the choppiness.

    Camera was a bit wonky to me as well, As it seems I could look down and behind myself, which would then sort of make the camera stuck until I tried to jump and then the camera would unlock.

    Also at one point I fell in a hole (one square in size), I was able to continue walking through the terrain but I (the camera) was stuck at that height. Once again not sure if this is a "normal" issue, or one caused by the choppiness on my end.

    I would be interested in testing a build without SESSAO.

    Thanks for showing off your work.
     
  31. RiokuTheSlayer

    RiokuTheSlayer

    Joined:
    Aug 22, 2013
    Posts:
    356
    The jumping high thing is because of framerate. I forgot to use time.deltatime in the jumping code.

    As for the choppiness, I realized that I set up multi-threading completely wrong. Tomorrow I'm going to re-do it. That's most likely why it's not working as well as it should be.

    The camera rotation isn't clamped correctly yet. Also going to work on that.

    And yeah, if you stand half-way into a block, you can place one there and clip into the terrain. Just a minor oversight.

    And as for a build without SESSAO, I'm working on the GUI more tomorrow. It'll probably be an option to turn it off and on. Though, I'd like to let you know that it's probably not going to affect your performance (Obviously depending on your graphics card, but still). SESSAO is really fast.
     
  32. KiwyVoxel

    KiwyVoxel

    Joined:
    Jan 14, 2015
    Posts:
    64
    I just finished to implement threading for my project, so i can now tell you how i did it :
    • I based my implementation on a consumer/producer queue, with a number of worker thread equals to my cpu count -1 (for the main thread).
    • I keep an array of my meshingScripts objects, so each of them has its own memory allocation.
    • And finaly i replace every Unity function (Mathf, vector3, quaternion, etc...) that my meshing scripts was using, so they could be threaded.
    Previously i was using coroutines, and the change of speed is remarkable. You can try it on my project page (in my signature).
     
  33. RuinsOfFeyrin

    RuinsOfFeyrin

    Joined:
    Feb 22, 2014
    Posts:
    785
    @KiwyVoxel

    Quick question for you.

    With your multiple background threads, how are you handling proper execution order of Terrain Gen, Lighting Gen, Mesh Gen, Mesh Rendering? Or are you not? The reason i use a single background thread for all those steps is that all neighboring chunks have to of reached a certain step before the chunk you are working on can go to the next step.

    If this is not done you will see inconsistencies in both terrain generation (with the likes of trees spilling to a new chunk) and lighting artifacts/issues.

    I found with multiple threads attempting to do this that a lot of times threads were stuck waiting for a neighbor chunk to get to its next step before they could finish their work. Ensuring proper execution order basically made more then one background thread handling these steps rather pointless I found, so I was wondering how you were handling it?


    Also Just an FYI not all unity code is not thread safe. You can use a Vector3 in another thread as just one example.
     
  34. KiwyVoxel

    KiwyVoxel

    Joined:
    Jan 14, 2015
    Posts:
    64
    For the chunk's workflow i am using a Finite State Machine (empty, needVertex, needMesh, etc..). it makes very clean code.

    I let Unity handle mesh rendering, and lighting is calculated by my shader (i am not sure it is usefull to calculate this on the cpu, as its the gpu job). So i dont need to wait for the other chunks. But i still have lots of work to do for this part.

    Terrain generation is done by density function from the vertex calculation, for now. I am thinking to re-implament a voxel array, with a dedicated worker thread for r/w access to speed up density checks and maybe to allow hard drive save.

    I use as many worker thread as cpu count - 1 (for the main thread). The only task multithreaded is the vertex calculation (Dual Contouring, marching cubes or boxel algorithms). Chunk managment is on the main thread.

    As for Unity function, i had multiple errors with multithreading so i chose to avoid them as much as possible.
     
    Last edited: Jul 13, 2015
  35. RuinsOfFeyrin

    RuinsOfFeyrin

    Joined:
    Feb 22, 2014
    Posts:
    785
    @KiwyVoxel

    Ah ok makes sense now, i do pretty much the same thing. I just thought from your previous description you had multiple threads plugging away at doing terrain generation and the likes of such.
     
  36. JasonBricco

    JasonBricco

    Joined:
    Jul 15, 2013
    Posts:
    956
    Could you elaborate on how you do this? I'm relatively new to shaders. I'm currently doing the flood fill on the CPU to generate an array of colors and then sending those to Unity for the lighting. I'm guessing your way that uses the shader is significantly different and much better performing.

    Edit: although I am not sure how much this applies to non-cubic voxel engines, as I have no experience with those.
     
  37. KiwyVoxel

    KiwyVoxel

    Joined:
    Jan 14, 2015
    Posts:
    64
    Shaders are specialized programmes that work on the gpu of the graphics cards. Hence instead of overloading the cpu with lighting calculation i let as much work as possible to the gpu and Unity. So i created a triplanar shader and one material by voxel type. And i take into account submeshes in my mesh creation.

    One important thing to notice, and as i read it from time to time on this forum, is that our utilization of voxels is not the most efficient. We use hermite data (as voxel) to calculate, then we convert the result into a more commun object, the mesh, to enter the Unity rendering pipeline. Hence we bypass a lot of optimization capability accessible on on the gpu. Especially with methode like clipmaps as Voxel Farm use it.

    I read that Unity rendering pipeline was inaccessible, i am not sure if it is always the case with 5.0. But there is a Voxel Farm Unity plugin in work, and i wonder what and how exactly they are doing it.
     
  38. Holag

    Holag

    Joined:
    Jul 20, 2015
    Posts:
    1
    So hey,

    Now i have a question too. How can i make the nice colorfull grass like in cubeworld?

    I hope anyone can help me :)
     
  39. OMGWare

    OMGWare

    Joined:
    Mar 4, 2014
    Posts:
    24
    Hey folks,

    so I figured I would like to share some footage of what I managed to achieve a few months ago, mainly thanks to this thread, some great advices and lots of brain burns.
    This is a playlist of all the footage I recorded during the development: https://www.youtube.com/playlist?list=PLeogF33yjmN2fptj5h8UigmkLhUzgi8jl

    An example video from the playlist showing the latest water simulation:



    I know it's still basic implementation and all, there is no gameplay yet, in fact I just worked on it for 1 month, managing to put in just few hours of spare time from my job each day, but figured it was enough to show something on video.
    I implemented infinite x/z terrain with chunks of 16x128x16, some weird 3D simplex noise generated terrain I didn't put much effort into (yet), voxel rgb lighting and AO, a basic prop import/export system that I would love to expand to include meshes done in external apps like Qubicle, some simple but pretty water physics, and everything is multithreaded using a very simple state machine with queues for chunks in various states.
    It's been a while since I put my hands on it, haven't had much time lately but there are still lots of things I would love to put into it in the future.

    That's it, wanted to share my progress in thank to the community and people on this thread for all the (mainly indirect) help they've been giving all this time, as a programmer I find these block engines really fun, very versatile and open to lots of ideas :)
    This is also my absolute first project in 3D using Unity, love this engine!
     
    Zimbres, Jamster and Azmar like this.
  40. Aler-Zampi

    Aler-Zampi

    Joined:
    Jul 8, 2012
    Posts:
    6
    Guys, thanks for a lot of information what you collected here!

    I'm working on my own game project where I needed some voxel engine. I'm already done with some prototype solution, but It's not so efficiency as I want. I need to generate 0.1 scaled voxels for one tile on with 30x2x30 field of view.

    It's a lot of calculation: 300x20x300 voxels in screen what means 1 800 000 generation operations and a more operations for ambient, quad draw...

    How you done with that?

    http://prntscr.com/7ztj4j
     
  41. CorWilson

    CorWilson

    Joined:
    Oct 3, 2012
    Posts:
    95
    Your water implementation reminds me of the way Dwarfcorp does their water. Question: how do you make it so that the water blocks change height based on the liquid level? I assume this involves manipulating the vertices or shader magic.
     
  42. macdude2

    macdude2

    Joined:
    Sep 22, 2010
    Posts:
    686
    This looks dope! Just curious, would your simulation work for say, filling up a tank? Could you make it so that the blocks dont have a finite lifetime?
     
  43. OMGWare

    OMGWare

    Joined:
    Mar 4, 2014
    Posts:
    24
    Indeed I collected all the info I could, including the blog post about Dwarfcorp's water, then came up with my own implementation (which is cellular automata based), I wanted to give the idea of water drops with varying size when falling from high places, and a visible growing volume. The water blocks vertices are just manipulated via code, I decide how to present them based on what's the state and volume of neighbor blocks, no shader magic was used

    Yeah it's really fun to work with, especially to destroy areas near or under the ocean water and look those fill up so nicely!
    To answer your question: water blocks don't have a finite lifetime, they just have a volume that spreads towards neighbors air blocks or water blocks with lower volume, then there is a minimum volume threshold for them to appear visible, under that threshold they just "disappear".
    This means that if you fill a tank the water stays in there, if you fill it with more water it just overflows outside the tank naturally, you can actually see this working in a previous video (devlog #8) of my first implementation on my channel.

    On the other hand, if anyone is curious about how "ocean blocks" work, they just are infinite sources of water (infinite volume), and are in a sleeping state by default. They wake up when neighbor blocks get modified, and return to sleep after a while if there isn't anymore water flowing from them.
     
  44. CorWilson

    CorWilson

    Joined:
    Oct 3, 2012
    Posts:
    95
    Smart on the logic for the water blocks. How much computer power does it take to pull off this slick technique? If you're constantly updating blocks that fast, I assume you either optimized it really well or you just have a very good CPU.
     
  45. OMGWare

    OMGWare

    Joined:
    Mar 4, 2014
    Posts:
    24
    On my current i7 4970k (pretty good CPU), the simulation step for roughly 10k active water blocks takes an average of 2-3ms, but I didn't put too much effort in optimizing it more.
    I haven't yet implemented a framerate control for the simulation, in fact with fewer water blocks sometimes it even runs too fast to have physical meaning.
    The fact that the block engine is multi-threaded makes it pretty fast, though the water simulation is currently running on the same thread together with block generation and meshing, so that could be optimized even more.
     
  46. RSH1

    RSH1

    Joined:
    Jul 9, 2012
    Posts:
    256
    Since upgrading to Unity 5, my UVs no longer show on Android devices (they still work fine in the editor). Anyone have any idea what might be the problem?

     
  47. Tempetek

    Tempetek

    Joined:
    Jul 28, 2014
    Posts:
    6
    Hey,

    My turn to report some progress on my game. Following everything on this thread, I tried to optimize everything as much as possible, I took the best of everything and added the best I known, and here is the result :




    With, of course, statistics (I used alexzzz Performance Monitor) :


    The world is 512*512*512, each chunks is 32*32*32, textures are 256*256, the world is infinite in each three axis. Mesh total isn't counting empty chunk (They doesn't need rendering, and thus would just F*** up the performance value). FPS (even if it isn't shown) are at maximum (60 FPS). The RAM used is 1-2 Go. My computer specs are :

    Graphics Card: NVIDIA GeForce GTX 760
    Processor: Intel(R) Core(TM) i7-4770 CPU @ 3.40GHz

    For this result I mainly used alexzzzz report on his progression, and modified it a bit to make it even faster (I don't know if I've got the permission to use his code tho, and I couldn't pm him for whatever reason). There's also vertices distortion, based on alexzzzz's, and a beautiful realistic sky (Not shown). For the lighting, I did nothing except using Unity shadows and a directional, I had no problem with it, and it was faster and better than coding it.

    If you want anything concerning what I've done, feel free to ask, I can share what I found and what I used. It'd be selfish not giving anything back when I've took so much on this thread.

    - Tempetek
     
  48. CorWilson

    CorWilson

    Joined:
    Oct 3, 2012
    Posts:
    95
    I'm trying to use vertex distortion to make more slopey water meshes. Got any advice on that?
     
  49. shadbags

    shadbags

    Joined:
    Jul 14, 2014
    Posts:
    5
    Would love to see some source code / assetpackages / write ups on this. You would have some really popular tutorials if you made one that covered it up to that point.
     
  50. Tempetek

    Tempetek

    Joined:
    Jul 28, 2014
    Posts:
    6
    (Sorry for late response)

    Depends on what you really wants to do. If you just want some nice distortion to make it like there is waves on the surface, you can just use a noise to displace the vertex (Should give you a fairly good result, be carefull with vertex connected to solid blocks though). Otherwise, if you want it distorted to make the slopey look of Minecraft water, just make a function to calculate the flow level of the blocks (From 0 to 1) and distort the vertex accordingly, should work about right.
     
Thread Status:
Not open for further replies.