Search Unity

After playing minecraft...

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

  1. JohanHoltby

    JohanHoltby

    Joined:
    Feb 10, 2013
    Posts:
    89
  2. goldbug

    goldbug

    Joined:
    Oct 12, 2011
    Posts:
    696
  3. goldbug

    goldbug

    Joined:
    Oct 12, 2011
    Posts:
    696
    I originally started moving unity box colliders around the player. I found several problems with it, like sometimes the collider causing the player to move. Also, it gets really complicated once you want to introduce mobs. Finally, once in a while, some collision was not registered and the player would fall down through the ground. I eventually gave up on this.

    Then I tried making an optimized mesh collider for the terrain. There would be one mesh collider per chunk, with merged blocks. This worked somewhat better, and it let me have mobs. I actually released with this. However this also had a "fall through the ground" problem, was a bit of a memory hog, and caused lag. I eventually gave up on this as well.

    Then I wrote my own AABB mesh collider. No more falling through the ground problem.

    My final implementation is my own algorithm, taking advantage of the fact that all blocks are the same size.
     
    angrypenguin likes this.
  4. Cherno

    Cherno

    Joined:
    Apr 7, 2013
    Posts:
    513
    One other thing I'm currently working on: How to avoid the character being able to "cling" to vertical walls if he jump into a wall and keeps on pushing into the direction of the wall? As long as the force is applied due to the player holding the controller stick into the wall's direction, the character will stay in mid-air. I can change the wall's (and thus, floor's) physics material to one that makes him slide down on contact, but this also applies to the ground so it's like ice.
     
  5. JohanHoltby

    JohanHoltby

    Joined:
    Feb 10, 2013
    Posts:
    89
    AABB is something I have thought about but I want it to be plug and play with Unity since other will use it.

    Thank you for your thought process though!
     
    Last edited: Sep 26, 2014
  6. DavidWilliams

    DavidWilliams

    Joined:
    Apr 28, 2013
    Posts:
    522
  7. JohanHoltby

    JohanHoltby

    Joined:
    Feb 10, 2013
    Posts:
    89
    Since I don't I don't want to get frames dropped due to spikes in the static collider simulation needing to rebuild.
     
  8. jordantotty

    jordantotty

    Joined:
    Dec 15, 2011
    Posts:
    77
  9. Cherno

    Cherno

    Joined:
    Apr 7, 2013
    Posts:
    513
    Howdy folks, I finally found a way to apply decals to single blocks depending on their integrity. Only took me half a day ;)
    Code (csharp):
    1.  
    2. if(block.integrity < 1.0f) {
    3.  
    4.                string crackMatString = "crack1";
    5.                if(block.integrity < 1.0f && block.integrity >= 0.66f) {
    6.                  crackMatString = "crack1";
    7.                }
    8.                else if(block.integrity < 0.66f && block.integrity >= 0.33f) {
    9.                  crackMatString = "crack2";
    10.                }
    11.                else if(block.integrity < 0.33f && block.integrity >= 0.0f) {
    12.                  crackMatString = "crack3";
    13.                }
    14.              
    15.  
    16.                List<string> matStrings = new List<string>() {block.tMat, block.nMat, block.eMat, block.sMat, block.wMat, block.bMat};
    17.              
    18.                for(int s = 0; s < matStrings.Count; s++) {
    19.  
    20.                  string matStringNew = matStrings;
    21.  
    22.                  if(matStringNew.Contains("_crack1") || matStringNew.Contains("_crack2") ||matStringNew.Contains("_crack3")) {
    23.                    matStringNew = matStringNew.Remove(matStringNew.Length - 7);
    24.                  }
    25.  
    26.                  Material newMat = new Material(Shader.Find("Decal"));
    27.                  newMat.SetTexture("_MainTex", World.globalMaterials[matStringNew].mainTexture);
    28.                  newMat.SetTexture("_DecalTex", World.globalMaterials[crackMatString].GetTexture("_DecalTex"));
    29.  
    30.                  matStringNew = matStringNew + "_" + crackMatString;
    31.  
    32.                  newMat.name = matStringNew;
    33.                  if(World.globalMaterials.ContainsKey(matStringNew) == false) {
    34.                    World.globalMaterials.Add(matStringNew, newMat);
    35.                  }
    36.                  if(matStrings == block.tMat) {block.tMat = matStringNew;}
    37.                  else if(matStrings == block.nMat) {block.nMat = matStringNew;}
    38.                  else if(matStrings == block.eMat) {block.eMat = matStringNew;}
    39.                  else if(matStrings == block.sMat) {block.sMat = matStringNew;}
    40.                  else if(matStrings == block.wMat) {block.wMat = matStringNew;}
    41.                  else if(matStrings == block.bMat) {block.bMat = matStringNew;}
    42.                }
    43.              }
    44.  
    block is obviously the variable that holds a custom class for every single block in the world, this contains things like the textures (saved as strings), the integrity, etc.
    So I first check if the integrity is below 1.0 so I know it's damaged and needs an updated texture. So far, I haven't implemented texture changes upon "healing" of blocks.
    Then I check which crack material needs to be applied by looking at the integrity again.
    Then I create a List of strings that hold the six Material names of the block.
    I then cycle through these strings so every face of the block is updated.
    I then check if the material name already contains a "_crackX", and I remove it.
    Then I create a new Material, butthis one uses a Decal shader. The three different crack materials are also Decal Materials, with no texture in the main slot and the decal texture in the decal slot.
    I then fill the new material with textures. The main texture is the block's current (trimmed) texture, and the decal is from the crack decal material that was specified earlier.
    The new Material name is then given a suffix so we will know later that it is has been applied a crack decal.
    The global Material directory has the new material added then.
    Lastly, The new material name is applied to the right block material name variable.
    I assume that most people do things differently when it comes to Material storing and applying, but the underlying theory should be clear. I hope that helps anyone that tries to implement something similar. The good things about this is that only as many materials as needed are stored at any one point, so you don't need to create multiple different crack materials for every normal material you have, it all is done by script and only when needed.
     
  10. Jacksendary

    Jacksendary

    Joined:
    Jan 31, 2012
    Posts:
    393
    Hey guys I've lurked around this post for quite some time now and have learn a great amount from here so Thank you very much!

    Now I've started to play around with a "block" engine my self to learn more about procedural mesh generation and I've run into a few questions that I was wondering if any one could answer for me.

    First I've seen multiple people and tutorials completely regenerate a whole chunk when ever a change is made to the chunk, this being placing or removing a block but my thoughts is that this must be extremely inefficient rather than making the change directly to the mesh so basically my question is if it is possible to change the mesh without regenerate the mesh.

    Second I've seen some people make their own shading/light "engine" and I've played around with this my self both using the vertex colors/mesh.colors and unity's built-in lights, and from what I've tested out the built-in lights works just fine even with RGB, so why should one make his own lights/shaders, what's the pros about it other than possibly better control and exposure of methods, and is it even possible to make a "real time" voxel light engine that also is efficient? if so how can this be achieved?

    I've tried to search a round a lot for answers to these but it doesn't seem that too many places covers these "Advanced" topics so I decided to ask in here as people here seem pretty experienced!

    Thanks a bunch in regard! - Jackie

    EDIT: I actually though of another question that have bugged me, so in minecraft there is transparet block (glass, Doors, leaves, etc.) which all lie as individual textures. My guess is these gets converted into a spritesheet (I may be wrong) at run time, but how would I handle the transparency part as it is only a few of the textures that is actually in need of being transparent? I've also noticed that the grass is kinda special as the grass color changes depending on the biome, eg. jugle is very green'ish, and savanna is more green-yellow'ish, which is all decided by float values and a gradient palette. However changing the color on a diffuse shader with a whole sprite sheet will change every single texture so this seems to be out of the question, but using multiple textures seems also to be very "weird" and hard to do. The next solution I found was to use sub meshes but I find this to be a very weird and inefficient way of doing it. In my dream world I feel like I should be able to have every single block within a single mesh, but I may be wrong but help or solution ideas to this would be amazing. :)
     
    Last edited: Nov 22, 2014
  11. Vanamerax

    Vanamerax

    Joined:
    Jan 12, 2012
    Posts:
    856
    Regenerating the whole chunk isn't that expensive for me to do. Most chunks take about 8 - 10 ms for me, with a 32^3 dimension and I am using marching cubes to generate the mesh. Regenerating only parts of your chunk would imply too much householding for the code, which increases complexity a lot. Instead you are probably better off either bringing your chunk size down, or taking a look at optimizing your algorithm if this is a problem for you.

    The builtin point and spotlights come at a price as far as performance goes. You won't notice any effect when playing around, but when your game really gets along, you might notice a bigger performance hit. Now this may be less of a concern on a desktop, but especially if you are developing for consoles or even mobile, this will be a serious performance hit. Another thing, with the vertex based lighting, you only have to update the light when a chunk gets regenerated. With the builtin lights, they 'recaculate every frame' (on the GPU mostly, that is)

    Minecraft indeed converts those into atlasses on runtime (a while back, it only had this atlas on disk, but they seperated the files out and rebuild them at runtime, so it was easier for texture packs and whatnot). The trick is to use a seperate atlas for transparent blocks, and a seperate atlas for the foilage. The foilage is just a greyscale image that gets colored by a shader via a gradient pallete as you described.You could use submeshes or seperate meshes, which I think would be the best approach. This way you can make your non-transparent blocks just use a diffuse shader, as transparency is relatively costly, opposed to opaque rendering. Submeshes allow you to use different shaders for different parts of the mesh
     
  12. Jacksendary

    Jacksendary

    Joined:
    Jan 31, 2012
    Posts:
    393
    Thank you very much :) Currently creating a Mesh for me takes roughly 0.050-0.100 ms, I assume the long time is due to I also initialize and assign it to the needed components etc. and haven't optimazized the mesh creator yet. I'll see if I can simply recreate it and if it actually works well: I just though it could possibly be faster to only remove (if possible) a single block rather than recreating the whole chunk

    If I'm going to do a day/night cycle wouldn't I be in need of doing the same thing, recalculate the suns light projection each frame? If so would it still be "worth" it to actually make my own light engine/scripts to calculate?

    I guess my best option is to make submeshes then? but should I make a atlas for each individual block type or can/should I simply use the same atlas for all shaders/meshes?

    Thanks a lot for you help so far :D

    Edit: Also I forgot to ask, marching cubes algorithm, how does that one work exactly? I've heard of it multiple times but never really looked into/heard how it works.
     
    Last edited: Nov 23, 2014
  13. JasonBricco

    JasonBricco

    Joined:
    Jul 15, 2013
    Posts:
    936
    I really don't see why Unity doesn't just give us the ability to turn off the frame by frame updating and expose a function that we can call to manually update it when we feel the need. Can do exactly what it already does each frame, but we control when.

    Why not? Wouldn't this solve the issue? I have difficulty investing my time in making a lighting system when this is something Unity has built in. I want to use what I can from Unity and focus on what makes my game unique.

    They did say that they're looking into lighting for procedurally generated worlds, though. I'm interested.
     
  14. JasonBricco

    JasonBricco

    Joined:
    Jul 15, 2013
    Posts:
    936
    While I'm here, I have a question for you all. And that question is about mip maps. Without them, I see a great deal of aliasing - strange wavy patterns all over in the distance when I try to move.

    I turned on mip mapping and this generally fixes the issue (minus a few white dots around). Except it only works up to mip 5.

    Once you get past mip 5, there are too few pixels to distinguish between each block, and blocks get merged together. This causes coloration to become broken past mip 5 in the distance.

    Has anyone else run into this? If yes, now did you handle it? If no, which other method did you use to get around aliasing?
     
  15. Vanamerax

    Vanamerax

    Joined:
    Jan 12, 2012
    Posts:
    856
    0.050 - 0.1 ms? dont you mean seconds here? The biggest performance boost for me was not to do bound checks. Instead of checking for blocks in neighbouring chunks over and over again, I copy over the chunk data to a slightly bigger array and also copy over some padding data to that bigger array. That way, I dont have to do bound checks. This made my algorithm go from about 200 ms down to 20 ms. Huge performance boost here. What also helps is reducing the amount of dependencies you have. So instead of using neighbour chunks in all directions, try to only check for the neigbours on the positive axis for example (only x + 1, y + 1, z + 1 etc)

    As far as I know, the best way is the 'bake' the sunlight levels in the vertices of the mesh when updating your chunks. Then write a custom shader that has a float property [0-1], which multiplies the vertex sunlight with that property to get the actual sunlight value. You can multiply with a sun color after that if you want, to get the actual light color. For the day and night cycle, you simply modify this float property (0 for complete darksness, 1 for full daylight)

    You should make a submesh for every atlas you are using. Of course you can skip creating an extra submesh, if the chunks doesn't contain any block surfaces of that particular atlas. Atlasses should be devided per shader type at least. So tranparent blocks get an atlas, opaque blocks get one, you could do one for vegetation (both opaque and transparent maybe?). Then you could also think about bumpmapping, specular etc. You can also divide these even further, to prevent using too big atlasses. They should be about 2048 or 4096 or something. Try to find a balance for yourself here, as it greatly depends on your needs and blocktypes.

    this site explains it pretty well. It also mentions Dual contouring, basicly an improved variant on MC, which I have yet to implement myself.

    It is called lightmapping, and can only be precalculated at built time. GPU's work a bit different as opposed to CPU's, and therefore I dont think a turn on/off option is that straightforward as it might sound. Even if possible, you would run the risk of way too many artifacts with other lightsources, meshes moving etc. Not a viable option, even if it might sound like so at first.

    This is quite a common problem without a real solution. It is pretty much a side-effect from using an atlas. It is called pixelbleeding. You could try to pad your textures with a few more pixels to reduce it a bit, but that only helps in some cases. You could also keep an eye out on how you lay out your texture tiles on the atlas, preferably placing similar-looking textures side by side (for example, placing different kinds of dirt or ground next to each other will make the bleeding less obvious)
     
  16. JasonBricco

    JasonBricco

    Joined:
    Jul 15, 2013
    Posts:
    936
    I'd probably simply have it ignore any moving meshes (example: AI monsters). Maybe there's a better way, but that would be logical to me for now.

    The thing I don't get is that this is basically happening every frame. What's the difference between it happening every frame and happening just when I tell it to? Do I even have to care about what "it" is? All I know is that "it" is happening 60 times per second, and maybe I want it to happen less frequently than that. Is there any reason it HAS to happen that fast, assuming I already decide that I want to ignore moving meshes such as enemy AI?

    Side note: I am getting into more low level programming, and I'll definitely be learning this stuff in the future. As it stands now, though, I really am quite clueless about the low level details of lighting.

    Unity just won't make this easy. The solution should be: set the max mip map level to 5 and disallow any more after (would be nice if they would give us some control over the distance as well).

    I'm not sure what you're referring to when you say 'real solution', though. Care to elaborate?

    How does this work? Couldn't any chunk have any possible block type? And you can only put one atlas on a given chunk. Or would you have to do some stuff in code to handle this? I'm very new to this kind of thing and this is confusing!
     
  17. Vanamerax

    Vanamerax

    Joined:
    Jan 12, 2012
    Posts:
    856
    Lighting not only depends on the positioning of certain objects and lights, but also on your view angle. That said, you would have to recalculate the lighting every frame that the camera moves, which is effectively almost every frame. By using voxel lighting, you can bake most of the static lighting data into the mesh, and recalculate the view-dependent data every frame. (to render an object, you still somehow have to determine a certain color for a certain pixel, which happens in the shaders)

    There is no all-round solution to fix the problem of pixel bleeding that I currently know of. In some situations it is more obvious than in others. Like I said, this could even depend on the content of the atlas itself (how similar the tiles look), the maximum distance a player can see, etc. For example, maybe try to obscure very distant land with more mountains.

    You can put one atlas on a given subchunk. Each subchunk can use it's own shader with its own set of properties (thus you can change the atlas texture for each submesh). For example, if your chunk mesh surface only contains opaque blocks (and you have all your opaque blocks in a single atlas), you can just use a single submesh and assign the atlas to that. If you add, lets say, a glass block, you have to assign two submeshes, one for the opaque atlas, and one for the transparent atlas. (for the transparant atlas, you also assign a transparent shader to that particular submesh, instead of a diffuse shader). Each submesh can basicly have it's own Material for that matter (see here and here)
     
    JasonBricco likes this.
  18. RuinsOfFeyrin

    RuinsOfFeyrin

    Joined:
    Feb 22, 2014
    Posts:
    785
    Hello Everyone and Happy Thanksgiving for those of you who celebrate thanksgiving.

    So I have a few questions rolling around in my head and was hoping to get some input from others, for now though ill stick to just the current one as it is kinda lengthy.

    City / towns / Village Generation: How are other people going about handling this?

    Its easy Enough for me to figure out where and how big cities should be, but not to actually determine what type of feature (house, shop, etc) should occupy a given location if they can potentially span more then 1 chunk.

    Simplest idea that would work would be to restrict features to being no bigger then a single chunk, which leaves buildings all being rather small, and i don't like this at all. This is easy enough though as you can easily determine what goes in any given chunk independent of its neighbor chunks by simply sampling some noise.

    I however would like to have the possibility of features that span several chunks. The problem comes in when the spawn point for a feature is not a loaded chunk yet but occupies enough chunks to fill a chunk that is visible. I could just have the feature "pop" in to place once the spawn point is loaded, but that brings up a second problem.

    What If the spawn point is visible and the feature is big enough that is runs out of my visible (and invisible buffer) area? How do you go about keeping track of changes that need to be made to a chunk that is not visible yet?

    Another possible solution to this is to say that features can only be a certain number of chunks in size at most, and then when generating a chunk ask all chunks within that distance if they are trying to generate a feature that should cover that chunk. The down side to this is that it limits the size of potential features to some pre-set size and that for every chunk i have to check the maxWidth*maxLength of chunks around it. So for a map of 16x16 chunks, with a max feature size of 5x5 im checking chunks 6400 times to generate the map, seems rather absurd.

    Wish List
    • I Need a way to determine if a given chunk is part of a larger feature , and what section of the feature it is.
    • Features can vary in shape and size, but the shape and size of each possible feature is known.
    • Ideally a chunk should be able to figure this out without having to ask questions of its neighbor chunks.
    • If it does have to ask questions of its neighbors, Id like to keep how far away / the number of neighbors we are asking to a minimum..
    • This all needs to be done in a fashion that when viewed "overhead" somewhat resembles a realistic city layout.

    This is seeming like an impossible wishlist, im not even sure its possible to do something like this generating everything on the fly.

    This leads me to my final "solution" that i still don't like which is when the world generates the first time i generate a handful (or more) of city layouts of given sizes and then use a noise sample to determine which layout i'm using for a given city. The upside to this is generating the cities this way would be trivial and allow me to pretty much meet all the criteria from my wish list.

    The downside to this is having to generate the cities a head of time means a limited number of cities (which i REALLY dislike), more time on initial generation of world, and more storage space would have to be used to save the generated city layouts (or more memory used to hold them if i generate them every time).

    [EDIT]
    I suppose I could have it generate a city layout the first time it encounters a chunk that belongs to the city. This would allow each city to be unique instead of loading from a pre-generated list, but would still cause the "poping" in effect when you come across the city as it would have to generate the entire layout in the background before it could start building the visible chunks . I would really like to avoid this kind of delay in the loading of the a city.
    [/EDIT]

    So to recap my questions are:
    • City / towns / Village Generation: How are other people going about handling this?
    • What If the spawn point of a feature is visible and the feature is big enough that is runs out of my visible (and invisible buffer) area?
    • How do you go about keeping track of changes that need to be made to a chunk that is not visible yet? (I have a 1 chunk buffer surrounding my visible area that normally handles this, but if a feature is extends out past that the information is lost).

    Well that is it in a nutshell.
    Hope to hear some great feedback and input, i'm sure there is more then a couple of you out there who have already tackled this or it is currently on your "to do" plate.


    Thanks,
     
    Last edited: Nov 27, 2014
  19. Jacksendary

    Jacksendary

    Joined:
    Jan 31, 2012
    Posts:
    393
    So I've tried for quite some time now to play with some shaders to have proper "voxel"/vertex shadows, but regardless of how much I've tried I just can't make the shader look very great or have the vertex colors/light work. Does any one have a shader they wouldn't mind sharing?
     
  20. neoshaman

    neoshaman

    Joined:
    Feb 11, 2011
    Posts:
    4,999
    Great jobs anyone, I have been following that since the beginning but only now posting to subscribe, I don't want to hunt down the right page anymore :p

    But since I'm here let's contribute.

    1. Atlas, bilinear and mip map is possible
    You will have to ping pong the UV, so it create an artifact of mirroring adjacent tiles, can be hidden with sufficient art fu.
    Source: http://www.gamasutra.com/blogs/Mark...ptimizing_For_Mobile_Using_SubTile_Meshes.php

    2. Cave culling
    I haven't seen this cave culling shared here so here it is:
    http://tomcc.github.io/2014/08/31/visibility-1.html
    http://tomcc.github.io/2014/08/31/visibility-2.html

    3. Bitmasking world gen and implicit material
    To speed up world gen and cut down memory usage you can separate the world gen in two passes:
    - The first pass only decide solid tile vs air/ cave carving. It mean you only need 1 bit instead of 1 byte (in the simplest engine). You can store row/column (as you wish) into a single int and have a 2d "logic" data chunk of only 32*32 bytes. It also allow you to apply computations on 32 blocks in one operation. It also compress much better which allow better sharing of chunk over internet.
    - The second pass determine the material (devoid of the part that decide solid/air) only at mesh rendering time, when a block is made visible. It cut down on redundant generation and save 1 byte to store material for all tiles as it is implicit.

    Of course, the vanilla idea is more suitable for destruction oriented engines. If you have creation you would need to maintain an array of custom placement that only store change, which still cut down on generation and storage.
     
  21. Cartucho

    Cartucho

    Joined:
    Nov 26, 2014
    Posts:
    3
    Cool! :)
    Is it possible to mesh using an implicit function for example ( -0.5(x^2+y^2+z^2) - (1/sqrt((x+1)^2+(y+1)^2+(z+1)^2)) - constant == 0 ) ?
     
  22. RuinsOfFeyrin

    RuinsOfFeyrin

    Joined:
    Feb 22, 2014
    Posts:
    785
    @jackie0100

    Are you talking about Ambient Occlusion shadows? Or are you talking about your Meshes casting shadows on to other meshes? What with shadows isn't working with Vertex Colors?

    If you are talking about AO shadows, then I did post a shader couple pages back. It supports texture atlasing (it is expecting an 8x8 tilemap), and vertex colors. There is certainly room for improvement on it, but hey I didnt even know what a shader was before i had to write that.

    I do have the following issues with it:
    1) There is little itty bitty (single pixel) white dots that sometimes appear within a given mesh triangle at the edges of the image as it is tilled. From reading i think this is a floating point precision error that depends entirely on your video card. Playing with the epsilon value may fix this, I havent tried yet.

    2) Filter Mode & Mip Mapping: For best results filter mode should be set to point, and generate Mip Maps should be disabled. I currently have not figured out how to properly do Mip Mapping with the texture atlas. As far as I know the only one to figure this out I think has been goldbug, though I don't think he has shared how. There are some suggestions on the forums for minimizing how noticeable the artifacts are when using mip maps, but i did not like any of them.

    Hope it helps,
     
  23. Jacksendary

    Jacksendary

    Joined:
    Jan 31, 2012
    Posts:
    393
    I'll try look it up, I'm not very skilled in the shader world and generally I dislike programming them. I would love to have something similar to what Alexzzzz have created way back with RGB lightning, but my whole problem is my scene/world is either very dark and gloomy or way to bright, with my current shaders I've played with or the last one, creates strange shadow artifacts. I can try post some images later as "proof" but what I would really love to have is something similar to this:

     
  24. RuinsOfFeyrin

    RuinsOfFeyrin

    Joined:
    Feb 22, 2014
    Posts:
    785
    @jackie0100

    Funny you posted that video, I would like to know how @alexzzzz has it displaying the lighting values floating around like you see around 1:24 seconds in to the video.

    As far as the lighting Alexzzzz is showcasing there you can achieve with the shader I posted (though he does not use Atlas if im not mistaken, he creates a submesh per material, which is how he is able to have his textures look so nice.

    Also if im not mistaken, his RGB lighting you are talking about isn't calculated in the shader, but is calculated on the CPU and passed to the shader as vertex colors, which the shader I posted you can do. I think the only thing he is calculating in the shader is how the sunlightLevel affects the final color outcome.

    The Ambient Occlusion you see is also calculated on the CPU by averaging the lighting value of the 4 faces that touch the vertex (on the plane you are currently looking at), solid blocks that emit no light are treated as a light value of 0 when calculating this. This is actually fake AO, but creates a nice look.
     
  25. alexzzzz

    alexzzzz

    Joined:
    Nov 20, 2010
    Posts:
    1,412
    True.

    It's a particle system with a texture sheet like these: Numbers 0-15.png Numbers 1-64.png
     
  26. Jacksendary

    Jacksendary

    Joined:
    Jan 31, 2012
    Posts:
    393
    I am somewhat aware of how it works with the calculations, I've already set up a some simple sub-mesh system and vertex coloring system my self that can change the color of a chunk (haven't setup for lightsources yet) but as said before my problem is more that the terrain looks extremely bright at some places and very gloomy at other places: https://dl.dropboxusercontent.com/u/13581369/Skærmbillede 2014-12-02 19.21.54.png as seen the snow is very bright and almost looks like it's self illumine, but the sandy areas looks very dark and gloomy.

    Edit: I tried take another texture and again it looks gloomy in the "desert" areas
     
    Last edited: Dec 2, 2014
  27. RuinsOfFeyrin

    RuinsOfFeyrin

    Joined:
    Feb 22, 2014
    Posts:
    785
    @alexzzzz
    Your a f-ing genius, now why did i not think of that.

    @jackie0100
    To me in the image you posted the sand looks ok, its the snow that looks very bleached. Also the skybox you have on there gives a very gloomy feel, which seems a bit more noticeable around the sand.

    How are you calculating the mixing of the existing tile color, and the lighting values? Depending on how these are mixed your results will vary. For example, my tiles in my sheet are the color they need to be when fully lit, this way I am never brightening them, I only darken them. This prevents the overly white appearance.
     
  28. nasos_333

    nasos_333

    Joined:
    Feb 13, 2013
    Posts:
    8,173
  29. Jacksendary

    Jacksendary

    Joined:
    Jan 31, 2012
    Posts:
    393
    Hmmm the skybox does indeed make things look slightly less gloomy when changed and the tint is tinkered with, it also creates an interesting way of changing the the skies for weather effects or similar, yet still I find the snowy areas extremely bright versus sandy areas which I still find a little gloomy, might be tweaking the textures in a image editor but I still scratches my head about how different it look in unity versus in minecraft as it is the same textures i'm currently using.

    EDIT: After tinkering further with the "biomes" I found that the reason desert looks so gloomy may be due to how extremely bright the snow is and there by "simply" creating a optical illusion. Still trying to look at how the snow can be improved.
     
    Last edited: Dec 2, 2014
  30. RuinsOfFeyrin

    RuinsOfFeyrin

    Joined:
    Feb 22, 2014
    Posts:
    785
    @jackie0100

    I was thinking about it, and I think I had a similar issue with the minecraft snow textures, just to white. The obvious solution is to darken the snow some. Easy enough of the top texture, the side with the dirt is a little harder, and i never got the two of them to look just right together. Eventually i gave up using the minecraft snow textures since they were just placeholder textures, and I didn't like the way minecraft combined the snow into the texture like that.
     
  31. Jacksendary

    Jacksendary

    Joined:
    Jan 31, 2012
    Posts:
    393
  32. Jacksendary

    Jacksendary

    Joined:
    Jan 31, 2012
    Posts:
    393
    So I've ran into an other sort of weird thing about targeting blocks correctly. Currently I'm using raycasts to find where I interact (I dont know if there is any other better methods atm) but when I do this I'm only able to get blocks when ever the player's look direction is within the following span { (1,0,0), (0,1,0), (0,0,1) } is other words, I can only remove blocks in front, right, and above me, all other blocks won't be removed. the same happens when I try placing blocks but is the inverse span of above, that is, below, left, behind.

    Player Interact code:
    Code (csharp):
    1.  
    2.         if (Input.GetMouseButtonDown(0))
    3.         {
    4.             Ray ray = Camera.main.ViewportPointToRay(new Vector3(0.5f, 0.5f, 0));
    5.             RaycastHit hit;
    6.             if (Physics.Raycast(ray, out hit, 30))
    7.             {
    8.                 Chunk chunk = hit.transform.GetComponent<Chunk>();
    9.                 if (chunk != null)
    10.                 {
    11.                     Vector3 p = hit.point;
    12.                     p += (hit.normal * -0.5f); //tried multiple hacks/fixes here
    13.  
    14.                     chunk.SetBlock(0, hit.point);
    15.                 }
    16.             }
    17.         }
    18.         if (Input.GetMouseButtonDown(1))
    19.         {
    20.             Ray ray = Camera.main.ViewportPointToRay(new Vector3(0.5f, 0.5f, 0));
    21.             RaycastHit hit;
    22.             if (Physics.Raycast(ray, out hit, 30))
    23.             {
    24.                 Chunk chunk = hit.transform.GetComponent<Chunk>();
    25.                 if (chunk != null)
    26.                 {
    27.                     Vector3 p = hit.point;
    28.                    
    29.                     chunk.SetBlock(1, hit.point);
    30.                 }
    31.             }
    32.         }
    33.  
    34.  
    Chunk placement code:
    Code (csharp):
    1.  
    2.     public bool SetBlock(byte block, Vector3 pos)
    3.     {
    4.         pos -= transform.position;
    5.         Debug.Log(pos);
    6.         return SetBlock(block, Mathf.FloorToInt(pos.x), Mathf.FloorToInt(pos.y), Mathf.FloorToInt(pos.z));
    7.     }
    8.  
    9.     public bool SetBlock(byte block, int x, int y, int z)
    10.     {
    11.         if ((x < 0) || (y < 0) || (z < 0) || (x >= World.ChunkSize) || (y >= World.ChunkHeight) || (z >= World.ChunkSize))
    12.         {
    13.             return false;
    14.         }
    15.  
    16.         Map[x, y, z] = block;
    17.  
    18.         StartCoroutine(CreateMesh()); //Recrates the mesh
    19.  
    20.         return true;
    21.     }
    22.  
    23.  
     
  33. RuinsOfFeyrin

    RuinsOfFeyrin

    Joined:
    Feb 22, 2014
    Posts:
    785
    Here is what i do,

    Code (CSharp):
    1.        
    2.         Vector3 colisionPoint;
    3.         Ray ray = Camera.main.ScreenPointToRay( new Vector2(Screen.width/2f, Screen.height/2f) );
    4.         RaycastHit hit = new RaycastHit();
    5.         Vector3 blockPos, nearestBlock;
    6.  
    7.         if (Physics.Raycast(ray, out hit, 20.00f) == true)
    8.         {
    9.             colisionPoint = hit.point;
    10.             Vector3 hp = colisionPoint + (0.0001f * ray.direction);
    11.             int x = Mathf.CeilToInt(hp.x) - 1;
    12.             int y = Mathf.CeilToInt(hp.y) - 1;
    13.             int z = Mathf.CeilToInt(hp.z) - 1;
    14.            
    15.             blockPos = new Vector3(x,y,z);
    16.             nearestBlock = blockPos + hit.normal;
    17.          }
    18.  
    It steps the collisionPoint in the direction of the ray a small amount so that you can accurately determine the block you have the center of the screen over because the collisionPoint is not within that particular block, but on the surface of it. This gets both the block you have the center of the screen over (Stored in blockPos), and also the closest block to you from the block on the face that you have the center of the screen over(stored in nearestBlock).

    Hope that helps.
     
  34. Jacksendary

    Jacksendary

    Joined:
    Jan 31, 2012
    Posts:
    393
    Thanks a lot! works like a charm now, not entirely sure why a previously version didn't work as it was almost equal to the one you posted.
     
  35. Cherno

    Cherno

    Joined:
    Apr 7, 2013
    Posts:
    513
    Horridoh! I've been seeking to replace my physical light-based solution with one similar to Minecraft, with modifiying vertex colors depending on the distance from a given light emitting cell. So far, I didn't got it to work. Could someone please explain, in general terms, the process behind the system, especially how it works in tandom with the normal mesh-generation / chunk updating?
     
  36. RuinsOfFeyrin

    RuinsOfFeyrin

    Joined:
    Feb 22, 2014
    Posts:
    785
    Hey cherno,
    Figure ill answer your question since I hate asking a question and getting no response.

    One thing real quick though. There is some pretty detailed explanations of how to do the lighting system on the forum already, as well as links to some articles people have written. These posts and articles range from a basic overview to very in-depth so if you need more information then im going to provide, please take the time to go further back in the forums for better answers. Specifically if you go searching Alexzzzz talks about it some (and if i remeber a nice tip on handling the addition and subtration of blocks and how to reprocess the lighting faster) and Goldbug also touches on it some as well and gives some hints at speeding up the process using RLE, someone also posts a link to another forum where another person (for some reason sailene or something like that pop in to my head as their name) goes over the process in depth as well.

    So first I suppose ill answer how the lighting system fits in to mesh generation and chunk updating. Keep in mind this is a basic outline, and more goes in to it then what I am going to cover.

    Chunk Generation/ Re-Generation Steps
    1. Generate Terrain Data
    2. Generate Lighting Data
    3. Generate Mesh Data
    4. Generate Actual Mesh
    5. When changes are made to an active chunk, the chunk that was modified is added to a priority que (priority is based on distance from player). This essentially starts the chunk back at step 2 in this list (Generate light, mesh data, then mesh).

    Points of importance:
    1. Steps 1-3 are handled in a separate thread from the main thread. This is to prevent the game from "locking up" while new chunks are loaded.
    2. The thread handling steps 1-3 is also responsible for monitoring the priority que for chunks that have had changes made to them.
    3. You can not process a chunk at any given step unless all neighboring chunks meet the following conditions:
      • All Neighbor chunks must be "active" by active I mean they must be loaded and capable of being processed.
      • All neighbor chunks are also ready to process the same step or have already processed this step.
    The reason for the conditions on point three is that surrounding chunks may affect the chunk you are actually working on.
    A neighbor chunk may generate a tree into the chunk you are looking at. This would affect both the lighting, and the mesh generation and creation processes. So we can not generate a chunks terrain unless all its neighbors are active and are in a state where they are ready to (or have already) had their terrain generated.

    You can not fully process the lighting for a chunk unless its neighbors are at least ready for lighting as well because light may spill in to neighbor chunks and if you have not generated the terrain yet you have no idea how to handle the light in the neighbor chunk.

    You can not generate the mesh data for a chunk unless all neighboring chunks are also ready (or have had) their meshes generated because neighbor chunks can affect the final block data and lighting data of the chunk you are currently looking at.

    If you do not handle your chunks if some sort of fashion similar to this when generating them you will run in to various visual issues, ESPECIALLY with lighting.


    So that is roughly how lighting generation fits in to everything. The next step would be the actual lighting generations process. This post was already a bit longer then i was initially anticipating and I have some other thing i need to attend to so later on today or tomorrow Ill go over the actual process somewhat of handling the lighting generation otherwise like i said there are lots of good information on it.

    Hope that helps some.
     
  37. Cherno

    Cherno

    Joined:
    Apr 7, 2013
    Posts:
    513
    Thanks for your reply! I should have added that my own voxel engine is a little different from the Minecraft-like ones that are the norm here. I don't have infinite terrain, but a set [,,] array of blocks that serve as one level. It's for a top-down coop dungeon crawler in Legend of Zelda style. So that means all chunks get loaded at the start and no further updating in that regard is neccessary.

    Currently, whenever an area needs to be updated (if the player digs into a block and removed it, or as part of the level editing process where I can select multiple blocks at once to change their textures, add or remove blocks or whatever) I call an UpdateChunks function that takes the area in the world that is will be updated, finds out which chunks are part of it, and rebuilds their meshes, colliders, navmeshes and sub-meshes (like water).

    After that, I call a function that's called UpdateTorches. Here, I check each block against an array of pre-made diagrams that give information about when a torch (light source) should be created. For example, if there is a solid floor below, and solid walls north and west, a torch will be created in the block's northwestern corner (a prefab is instantiated).

    This would be enough for physical lighting since the torch prefab has a Light component on it. Now, after a few days of testing, I managed to create an optional additional lighting solution with vertex lighting.

    When a torch is created, I also give the block a emitLight Value and Color. Then, I iterate through the whole edit area again and reset all the lighting values in it. Then comes another iteration; this time, I basically have each block make another loop around it in 8 spaces distance (the max value for lights). Whenever there's a strong enough light source in this loop, it gets added to the block's lightSources list.

    I use Bresenham's line algorithm to check if a light source is behind a wall, btw.
    After the loop is completed, the block is given a new light color based on all the lightsource's colors and their values, modified by distance. This color is then applied to the block's neighboring TNESWB vertices.

    It all works pretty good, I even made a simple script to update an object's vertex colors depending on the light color of the block it is positioned in.
     
  38. Jacksendary

    Jacksendary

    Joined:
    Jan 31, 2012
    Posts:
    393
    So I've ran into another problem while working which is about placing blocks when the "space" is occupied by a player or an entity. Atm I'm able to place a block on the same spot as the player or an entity which result in them falling through the world. As posted earlier I'm using ray casting to find where a block should be placed and placement works fine, but the raycast is will not nessesary return if there's an entity on the same spot.

    My first assumption was to make rays casts in a cross pattern within the space where I'm placing the block but my conclusion to this was that it looked more like a "work around" rather than a valid solution, and the raycast here may still not hit lets say "small" entities. Next I began to wonder if I was able to make a 3D rect area that could return anything that was inside that area but I wasn't able to find any information whether this was possible to do. The last solution which I personally think is a completely wrong way to do it, is to check whether or not the entity collides with the new block placed whenever the chunk is regenerated, and then rollback any changes made if any collision, but this seems like a weird and very late solution.

    I decided I would ask here how you guys handle such as I cant wrap head around a solution that I find "valid"
     
  39. Cherno

    Cherno

    Joined:
    Apr 7, 2013
    Posts:
    513
    I wrote a simple function to get all objects in a specified area. It takes an array of coordinates (my Coordinate class is just like a Vector3, but with ints instead of floats for xyz). So to get all objects in a single block space, you would just pass it an array with the single coordinate in it. You can also just give it the xyz values if you don't want to support an area that is larger than one block; In that case, the max values would by the xyz values you pass + 1 (or whatever sizes your blocks are).


    Code (CSharp):
    1. public List<GameObject> GetObjectsInArea(Coordinate[] areaCoords) {
    2.    
    3.         //this is specific to my system and will provide the min and max xyz values of the whole area; It returns a coordinate array with length 2: [0] has the coordinatet with the min xyz values and [1] has the max xyz values.
    4.         Coordinate[] minMaxCoords = GetMinMaxCoords(areaCoords);
    5.         Vector3 min = new Vector3(minMaxCoords[0].x, minMaxCoords[0].y, minMaxCoords[0].z);
    6.         Vector3 max = new Vector3(minMaxCoords[1].x, minMaxCoords[1].y, minMaxCoords[1].z);
    7.  
    8.         //this is the list of gameobjects that will be filled (or not) and returned
    9.         List<GameObject> objectList = new List<GameObject>();
    10.  
    11.         //this float serves as a sort of leeway so objects that are a fraction outside the limits also get updated.
    12.         float f = 0.5f;
    13.  
    14.         /*
    15.         //the most simple method would be to just get an array of ALL gameobjects in the scene
    16.         object[] obj = GameObject.FindObjectsOfType(typeof (GameObject));
    17.         foreach (object o in obj) {
    18.             GameObject go = (GameObject) o;
    19.             //...
    20.         }
    21.        */
    22.         //Personally, I have all "world objects" tagged as WorldObject, this way the list won't include things like torches, Game Managers, or even chunks objects.
    23.         GameObject[] gos = GameObject.FindGameObjectsWithTag("WorldObject");
    24.         foreach (GameObject go in gos) {
    25.  
    26.             float x = go.transform.position.x;
    27.             float y = go.transform.position.y;
    28.             float z = go.transform.position.z;
    29.  
    30.             if(x + f >= min.x && x - f <= max.x && y + f >= min.y && y - f <= max.y && z + f >= min.z && z - f <= max.z) {
    31.                 objectList.Add(go);
    32.             }
    33.         }
    34.  
    35.         return objectList;
    36.     }
     
  40. Jacksendary

    Jacksendary

    Joined:
    Jan 31, 2012
    Posts:
    393
    Hmm yeah, a solution like that was what I was afraid of may be necessary. I'm always a little hurt inside when I'm in need to find "all" objects, with name or tags and loop through them all rather than only checking within a subspace of the world.
     
  41. Cherno

    Cherno

    Joined:
    Apr 7, 2013
    Posts:
    513
    Well, if performance is an issue there, I guess it could be made slightly more efficient by keeping a static list of all gameobjects in the scene, adding to it whenever a new object is instantiated, and removing an object if it is destroyed, and then using this list to check min max positions against.

    Now for something completely different ;) :

    I am still stuck in my vertex-based lighting solution. I wonder how people here and elsewhere handle it: Do they use vertex lighting exclusively (so, unlit vertex shader with no physical light sources at all), or a mixture of physical and vertex-based (which, for me, created a hige problem because of the ambient light which is always influencing how things look), or some may even be using physicals-based lighting exclusively?
     
  42. Jacksendary

    Jacksendary

    Joined:
    Jan 31, 2012
    Posts:
    393
    You would still need to loop through the entire list, I know it's nano seconds we're talking about but I like to find the most optimal solution :)

    atm I'm still working on the RGB vertex coloring but I have an idea on how to make it. What I plan to do is to implement a light source block that have some properties on how hard the light is, how far it reaches, and then probably use raycasting to see whether it reaches a target area, or if something blocks it.
     
  43. Cherno

    Cherno

    Joined:
    Apr 7, 2013
    Posts:
    513
    I strongly usggest not using Raycasting (which will get very expensive), but rather a Bresenham algorithm to find out if two coordinates are connected by a line uninterrupted by walls:

    Code (CSharp):
    1. public bool LineBlocked (Coordinate start, Coordinate end) {
    2.  
    3.         bool steepXY = Mathf.Abs(end.y - start.y) > Mathf.Abs(end.x - start.x);
    4.         if (steepXY) { Swap(ref start.x, ref start.y); Swap(ref end.x, ref end.y); }
    5.        
    6.         bool steepXZ = Mathf.Abs(end.z - start.z) > Mathf.Abs(end.x - start.x);
    7.         if (steepXZ) { Swap(ref start.x, ref start.z); Swap(ref end.x, ref end.z); }
    8.        
    9.         int deltaX = Mathf.Abs(end.x - start.x);
    10.         int deltaY = Mathf.Abs(end.y - start.y);
    11.         int deltaZ = Mathf.Abs(end.z - start.z);
    12.        
    13.         int errorXY = deltaX / 2, errorXZ = deltaX / 2;
    14.        
    15.         int stepX = (start.x > end.x) ? -1 : 1;
    16.         int stepY = (start.y > end.y) ? -1 : 1;
    17.         int stepZ = (start.z > end.z) ? -1 : 1;
    18.        
    19.         int y = start.y, z = start.z;
    20.        
    21.         // Check if the end of the line hasn't been reached.
    22.         for(int x = start.x; x != end.x; x += stepX)
    23.         {
    24.             int xCopy = x, yCopy = y, zCopy = z;
    25.            
    26.             if (steepXZ) Swap(ref xCopy, ref zCopy);
    27.             if (steepXY) Swap(ref xCopy, ref yCopy);
    28.            
    29.             // Replace the WriteLine with your call to DrawOneBlock
    30.             //Debug.Log("[" + xCopy + ", " + yCopy + ", " + zCopy + "], ");
    31.            
    32.             errorXY -= deltaY;
    33.             errorXZ -= deltaZ;
    34.            
    35.             if (errorXY < 0)
    36.             {
    37.                 y += stepY;
    38.                 errorXY += deltaX;
    39.             }
    40.            
    41.             if (errorXZ < 0)
    42.             {
    43.                 z += stepZ;
    44.                 errorXZ += deltaX;
    45.             }
    46.              //World.blocks[,,] being the block array; fillData is an int variable of my Block class, if you use an int[,,] array, fillData would'nt be there.
    47.             if(World.blocks[xCopy, yCopy, zCop].fillData == 1) {
    48.                 return false;
    49.             }
    50.         }
    51.         return true;
    52.     }
    For my vertex lighting, I know the basics but I am still experimenting with how the following variables interact:
    1. ambient light (NOT unity's ambient light, which is ignored, but rather a custom color that is used for all vertices of the terrain as their default color)
    2. Block tint (a color that tints the block's textures, theoretically ignoring the need for multiple textures of different colors by only havbing one texture in greyscale)
    3. light from light sources
     
  44. Jacksendary

    Jacksendary

    Joined:
    Jan 31, 2012
    Posts:
    393
    Ah true, good call!
     
  45. ostrich160

    ostrich160

    Joined:
    Feb 28, 2012
    Posts:
    679
    It is VERY poorly optimized, I remember reading something about its cave system being really bad
     
  46. Jacksendary

    Jacksendary

    Joined:
    Jan 31, 2012
    Posts:
    393
    It doesn't help much that it is running on JVM either ;)
     
    Last edited: Dec 19, 2014
  47. Cherno

    Cherno

    Joined:
    Apr 7, 2013
    Posts:
    513
    I think it's funny that you replied to a question that was asked on the first page of this as of now 52-page thread ;)
    I write this just in case you didn't realize that :)
     
  48. ostrich160

    ostrich160

    Joined:
    Feb 28, 2012
    Posts:
    679
    Well you just answered your own question. If its first page, what am I gonna see first
     
  49. Ahmio

    Ahmio

    Joined:
    Mar 16, 2014
    Posts:
    7
    ?? JVM is faster than C# (.NET)
     
  50. Captain Morgan

    Captain Morgan

    Joined:
    May 12, 2013
    Posts:
    144
    My surface shader, that work with light sources.

    fhw34234234к.JPG
     
unityunity