Search Unity

Spherical Terrain Shader

Discussion in 'Scripting' started by BigBGros, Aug 30, 2013.

  1. BigBGros

    BigBGros

    Joined:
    Aug 30, 2013
    Posts:
    21
    I have search whole internet searching for a spherical terrain shader for Unity. I want to texture a sphere depending on the distance(altitude) between each vertice and the origin of the sphere(center pivot). It could be great to put from 4 to 8 maps in the sphere. I've no idea about shaders.

    I put an example there:

    $planet.png


    Can anyone help me?

    Thanks in advance
     
    ThiagoCunhaTCB likes this.
  2. jc_lvngstn

    jc_lvngstn

    Joined:
    Jul 19, 2006
    Posts:
    1,508
    Here's just my suggestion, based on my limited knowledge of shaders:

    First, go into blender and create an icosphere with 7 divisions.

    $icosphere-7 divisions.jpg

    Export that to unity as an obj. Import it into Unity.
    There, that is your planet with a pretty darn detailed mesh.

    Then, adjust the heights of each vertex based on its distance and vector from the planet center, adjusting each vertex out by the altitude. So if you are increasing the altitude of a vertex by um...10% above the current surface, you would take the current vertex vector from the center of the planet, multiply it by 1.1...there is your new vertex position. Are you getting your height data from a noise function, or from pregenerated data like a height map?

    Since it is about 41k vertices, that is plenty to get in one mesh. And I would expect this height adjustment to easily be fast enough to do in real time.

    IMO, the only special shader you need is something that can do multipass blending, like the awesome Relief Terrain Pack. It has excellent shaders that do this for arbitrary meshes.

    Good luck, hope that helps.

    PS: I don't know how detailed you need the terrain on your planets to be. 6 divisions would certainly give you better performance if you really need it, and your planets are far away.
     
  3. BigBGros

    BigBGros

    Joined:
    Aug 30, 2013
    Posts:
    21
    Thanks for answering jc_lvngstn.

    I have this at the moment:

    $Planet.png

    The terrain is random Perlin Noise generated. And i need a shader for that, because as said, the planets are random generated, i can't unwrapp anything because the planet is created at runtime.

    I attach a video for what i'm looking for... i only need the shader part but for terrains, with 4 or 8 layers



    I hope someone can help me.

    Thanks in Advance.
     
  4. hpjohn

    hpjohn

    Joined:
    Aug 14, 2012
    Posts:
    2,190
    So you just want a shader to pick a bitmap based on vertex distance from origin, thats equivalent to the scalar of the vertex position
    You could probably also save a squareroot calculate by just using the sqrMagnitude of the position, since its all relative.
    You could get it with vertex.x * vertex.x + vertex.y * vertex.y + vertex.z * vertex.z in the vert shader, and then maybe pass that to the fragment shader in a color, and use that to blend between the various maps.
     
  5. BigBGros

    BigBGros

    Joined:
    Aug 30, 2013
    Posts:
    21
    I understand you hpjohn... but i have no idea about Shaders programming... Can you put me an example code for 4 textures or 8? I'd be greatfull.

    Thks in advance.
     
  6. hpjohn

    hpjohn

    Joined:
    Aug 14, 2012
    Posts:
    2,190
    Here is an example I whipped up, it blends between 5 maps by height, but only works for spheres at (0,0,0), and it's exceptionally verbose. Also wont work on low shader-model cards, because of number of registers and arithmetic instructions

    the _Blend0to1and1to2 vectors are just a neater, more compact way of providing 4 floats separately - and the values define the start and end height of each blend section


    The heights of each vertex are stored temporarily in a color (the position semantic is gone by the time you get to the frag shader) and then a series of if-tests determines which 2 maps to lerp between.
    This probably isn't a very efficient solution, but you wanted a starting point.

    Code (csharp):
    1. Shader "Custom/planet" {
    2.     Properties {
    3.         _Tex0 ("Tex 0", 2D) = "white" {}
    4.         _Tex1 ("Tex 1", 2D) = "white" {}
    5.         _Tex2 ("Tex 2", 2D) = "white" {}
    6.         _Tex3 ("Tex 3", 2D) = "white" {}
    7.         _Tex4 ("Tex 4", 2D) = "white" {}
    8.        
    9.         _Blend0to1and1to2 ("Blend between 0 and 1, 1 and 2", Vector) = (0,1,2,3)
    10.         _Blend2to3and3to4 ("Blend between 2 and 3, 3 and 4", Vector) = (0,1,2,3)
    11.        
    12.     }
    13.     SubShader {
    14.         Lighting Off
    15.         Fog { Mode Off }
    16.         Pass {
    17.             Blend SrcAlpha OneMinusSrcAlpha
    18.             CGPROGRAM
    19.                 #pragma vertex vert
    20.                 #pragma fragment frag
    21.                 #include "UnityCG.cginc"
    22.                 #pragma target 3.0
    23.                 sampler2D _Tex0;
    24.                 sampler2D _Tex1;
    25.                 sampler2D _Tex2;
    26.                 sampler2D _Tex3;
    27.                 sampler2D _Tex4;
    28.                 float4 _Blend0to1and1to2;
    29.                 float4 _Blend2to3and3to4;
    30.                 uniform float4 _Tex0_ST;
    31.        
    32.                 struct v2f {
    33.                     float4 pos : SV_POSITION;
    34.                     float2 uv : TEXCOORD0;
    35.                     float4 col : COLOR;
    36.                 };
    37.                
    38.                 v2f vert (appdata_base vInput) {
    39.                     v2f OUT;
    40.                     OUT.pos = mul (UNITY_MATRIX_MVP, vInput.vertex);
    41.                     OUT.uv = TRANSFORM_TEX(vInput.texcoord, _Tex0);
    42.                     OUT.col = length(vInput.vertex);
    43.                     return OUT;
    44.                 }
    45.                
    46.                 half4 frag (v2f fInput) : COLOR {
    47.                     half4 c0 = tex2D (_Tex0, fInput.uv);
    48.                     half4 c1 = tex2D (_Tex1, fInput.uv);
    49.                     half4 c2 = tex2D (_Tex2, fInput.uv);
    50.                     half4 c3 = tex2D (_Tex3, fInput.uv);
    51.                     half4 c4 = tex2D (_Tex4, fInput.uv);
    52.  
    53.                     if (fInput.col.x < _Blend0to1and1to2.x) return c0;
    54.                     if (fInput.col.x > _Blend0to1and1to2.x  fInput.col.x < _Blend0to1and1to2.y) return lerp(c0,c1,((fInput.col.x - _Blend0to1and1to2.x)/(_Blend0to1and1to2.y-_Blend0to1and1to2.x)));
    55.                     if (fInput.col.x > _Blend0to1and1to2.y  fInput.col.x < _Blend0to1and1to2.z) return c1;
    56.                     if (fInput.col.x > _Blend0to1and1to2.z  fInput.col.x < _Blend0to1and1to2.w) return lerp(c1,c2,((fInput.col.x - _Blend0to1and1to2.z)/(_Blend0to1and1to2.w-_Blend0to1and1to2.z)));
    57.                     if (fInput.col.x > _Blend0to1and1to2.w  fInput.col.x < _Blend2to3and3to4.x) return c2;
    58.                     if (fInput.col.x > _Blend2to3and3to4.x  fInput.col.x < _Blend2to3and3to4.y) return lerp(c2,c3,((fInput.col.x - _Blend2to3and3to4.x)/(_Blend2to3and3to4.y-_Blend2to3and3to4.x)));
    59.                     if (fInput.col.x > _Blend2to3and3to4.y  fInput.col.x < _Blend2to3and3to4.z) return c3;
    60.                     if (fInput.col.x > _Blend2to3and3to4.z  fInput.col.x < _Blend2to3and3to4.w) return lerp(c3,c4,((fInput.col.x - _Blend2to3and3to4.z)/(_Blend2to3and3to4.w-_Blend2to3and3to4.z)));
    61.                     return c4;
    62.                    
    63.  
    64.                 }
    65.             ENDCG
    66.         }
    67.     }
    68. }
     
    Last edited: Sep 1, 2013
    ncortiz likes this.
  7. BigBGros

    BigBGros

    Joined:
    Aug 30, 2013
    Posts:
    21
    You are a Master of Shading!!!

    Thanks a lot.

    Here is the result right now:

    $planet_sahder.png

    Is possible to be affected by light and texture tiling? It would be greatfull and fully completed if so.
     
  8. hpjohn

    hpjohn

    Joined:
    Aug 14, 2012
    Posts:
    2,190
    Tiling already works in that example, except it uses the tiling of the 0th map for all 5 maps (change the x and y tiling in the first slot)

    Lighting&shadows is a whole other subject tho, now you've seen this example, maybe you can work it into a surf shader, where the lighting is simpler to set up.
     
  9. Kortuga

    Kortuga

    Joined:
    Jul 8, 2013
    Posts:
    1
    Hey, I'm looking to somewhat emulate this planet-generation effect for a game. Can I ask how OP managed to generate the terrain with Perlin noise?
     
  10. Deadphyre

    Deadphyre

    Joined:
    Sep 26, 2013
    Posts:
    21
    That makes two of us. I've been able to procedurally generate an icosphere with the initial sides and subdivide it to where it's okay. I want to put in a LOD system to improve visual quality within a distance as I want to generate a 1:1 planet scale. With minimal verts at a distance and then increase that once you are a certain distance away. I had initially tried using a texture of the moon, just to see what it would look like but I ran into that ugly seam problem and I don't want to duplicate the verts along the seam. So I want to generate some terrain, some land mass, some mountains and some underwater oceanic terrain. I've found a few examples but it's all in OpenGL or DX and I'm not using either of those at the moment. I'm also learning as I go. How would I use that shader example listed above...or I should ask, how would I implement it. Like the OP, I'm a complete noob on shaders. Would I put it into it's own private/public void function and then run stuff through it?

    Also, the perlin noise. Would I just run all the verts through a noise function to change the distance from center. I've done some Noise generation with cube worlds (minecraft like) but the noise on a procedural sphere is just not grasping. I know this is a lot of questions but we all start somewhere right? It's very possible that this thread is outdated and no longer looked at but there is always hope.
     
  11. Sawdeth

    Sawdeth

    Joined:
    Mar 17, 2014
    Posts:
    1
    I know that it's been a couple of years ago, but back then you were able to subdivided the icosphere by 7 times. Since computing technology has slightly improved the rendering quality, I took the liberty of subdividing the icosphere 8 times, then I subdivided again in edit mode. I must say, it looks pretty darn good but slow as heck while loading.
     
  12. bloomingdedalus

    bloomingdedalus

    Joined:
    Aug 13, 2012
    Posts:
    139
    To create seamless perlin noise on any 3d mesh you just sample a 3d perlin generator at the points on the surface of the mesh - crosssections of 3d perlin noise look almost exactly like 2d perlin noise with the added bonus that placing a mesh "inside" the 3d perlin space and sampling it will always produce seamless noise on the mesh.
     
  13. Localguy65

    Localguy65

    Joined:
    Feb 10, 2013
    Posts:
    7
    I know this thread is a little old but I've been messing with this shader and I am not sure how to get shadows to work with it.

    Does anyone know how to convert this to the new Standard shader model?

    Any help would be greatly appreciated.

    Regards,
    Eric
     
  14. Googoo04

    Googoo04

    Joined:
    Nov 18, 2016
    Posts:
    2
    Hey BigBGros, I am also having trouble with creating procedural planets, though it's the terrain that is stumping me. I too have searched the entire internet for a solution, but nothing useful. Would you mind if I can see how you managed to do it?

    Thanks in advance
     
  15. Googoo04

    Googoo04

    Joined:
    Nov 18, 2016
    Posts:
    2
    I need help with my terrain, which looks like garbage. could help me?
     
    jason-fisher likes this.