Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
  • Help Room /
avatar image
3
Question by Fratyr · Aug 18, 2012 at 11:48 AM · proceduralgenerationspaceplanetplanets

Example of Procedural Planet generation?

Hi,

Does any one have share-able example of "Procedural Planet" generation script (pref. C#) or anything explains how game makers simulate "endless" space environment?

I want to toy with this technique to learn something new.

Thanks :)

Comment
Add comment · Show 2
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image DavidD · Aug 18, 2012 at 03:07 PM 0
Share

This is an extremely broad topic. I doubt it that anyone would have a script (probably more than 1) to share. Generating planets would be more complex than just generating terrain since the planets are round.

Firstly you would have to generate the planets themselves, then the terrain on the planet using perlin noise or some other algorithm, then textures, then LOD $$anonymous$$odels, then occlusion culling of some sort and this and that.

If you like coding and all that comes with it I suggest you look around and get familiar with the concepts like instantiating objects, generating terrain and maybe clouds. Take it one thing at a time and you won't get too overwhelmed. Focus on the task at hand.

Good luck!

avatar image Vampyr_Engel · Mar 16, 2017 at 09:11 AM 0
Share

I am interested in Procedural Planets for my game as well would like to use my current models rather than making whole new models though

2 Replies

· Add your reply
  • Sort: 
avatar image
6
Best Answer

Answer by Uncasid · Oct 05, 2012 at 04:44 AM

Last edit for this, but it should be placed at the top.. someone has done what I was suggesting here, and when you purchase, they give you the source: http://u3d.as/content/vander-imerso-nunes/etherea1-ethereal-planets/2Ph

well.. lets see.. i have done this sort of thinng before..

i used fbm for generating height map on the fly, used spherical harmonics to get the map to look correct at the poles, and used geoclipmapping to dothe planet.. now, when i added streets and such i used l-systems.

details.. i generated several textures for the planets, 1 for height, 1 for diffuse, 1 for normals, then some via masks for roads..
geoclipmapping, i tried to do spherical geo clipmapping, but that was a bit over my head and just couldn't get it to work. what this does is take a center point that is under your camera and make it maximum detail, then at a specific distance you have another level that is less detail which merges with the points from full detail section. you do this for 5 or so levels each with progressively less detail until you hit a flat surface. now the terrain data is stored in a toroidal array, which means you move all the verts / faces, NOT the camera (called camera space).

now, to tell you the truth.. it is a LOT of work getting this done.. google the specific words there and it will get you on your way :). also to note, i didn't do this in unity. if you have a hard time finding the stuff i am talking about, write back here and i will give you the links (i am on ipad and too lazy to get all the details for you ;) )

Edit (Not on the iPad anymore and not as lazy): the first one is on clipmaps, and this is a very good resource on how to do them. He talks about a few different kinds of clipmaps, and how to do them on the GPU http://www.cg.tuwien.ac.at/research/publications/2008/fruehstueck-2008-gpu/fruehstueck-2008-gpu-paper.pdf (Proof of concept here, it is possible in unity: http://www.youtube.com/watch?index=5&list=UU3twJEOXuPUgYkhIn-4TPug&feature=plcp&hl=id&v=0OS9Dh94x1c&gl=ID)

Now for Fractal Brownian Motion (think of it as an advanced version of perlin noise), this link is quite math intensive, but isn't as hard as it looks. The think about fbm is that it has octaves, which gives the impression that you are zooming in. http://harrisd.net/papers/Id/MandelbrotVanNess1968SIAM.pdf (this is fbm implemented) http://www.allegro.cc/forums/thread/604600

Now for l-systems.. These are actually quite easy to understand as well. The tree tool in unity already uses this type of system :) http://www.cs.purdue.edu/homes/aliaga/cs197-10/papers/p_cities.pdf

crap, had to edit again, forgot the spherical harmonics part: Spherical harmonics is used to bend textures at the poles to prevent a texture artifact that comes with texturing a sphere (http://jwhigham.files.wordpress.com/2010/05/uniformcloudsplanet.jpg)

as you can see, this is sort of a square peg in a round hole sort of problem.. You need to spherize your square texture to make it work. There are a few different methods to make this work, like the one used to fix the picture above: http://jwhigham.wordpress.com/2010/05/21/clouding-the-issue/ The problem you have is that you need to do this on the fly, as you are generating planets on the fly using a seed (I assume you are going for a galaxy, correct?) here is the math for you: http://www.ppsloan.org/publications/StupidSH36.pdf

now, I will be the first to admit, this took me a long while to understand, so here is a start on a cpu based implementation of the perlin noise + SH (can't give you everything, else you wouldn't learn :D) The code below was done in XNA, but the theory is the same no matter which engine you use

 /*  --------------------------------------------------------------------------------------------
  *  -   perlinPlanet
  *  --------------------------------------------------------------------------------------------
  *  Built by: Uncasid
  *  Last Updated: 10/13/10 4:00pm MST
  *  Description:
  *   This class is used to build a planet based on perlin noise.
  *   
  *  Requirements:
  *   + Content (mesh) for sphere
  */
 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using Microsoft.Xna.Framework;
 using Microsoft.Xna.Framework.Content;
 using Microsoft.Xna.Framework.Graphics;
 using Microsoft.Xna.Framework.Input;
 
 namespace Planet
 {
     class cpuPerlinPlanet : GameObjects._Prototypes.aBaseRenderableWorldObject
     {
         #region Fields
         //Old planet
         //private Primitives.cPrimSphere PlanetMesh;
         private Model PlanetMesh;
         private Effect shader;
         private Effect shaderPerlin;
         private Effect DepthAndNormalsEffect;
         //private Texture2D PlanetTex;
         private Texture2D PlanetNrmTex;
         private Texture2D PlanetSpecTex;
         private Texture2D CloudTex;
         private Texture2D gTexture;
         private cAtmosphere Atmosphere;
 
         private float PlanetSize;
         //private DepthStencilBuffer tmpBuffer;
         //private DepthStencilBuffer cachedBuffer;
 
         private Controllers.Lights.LightTypes.genericLight _Light;
 
         #endregion
 
         private int Seed;
 
         //Texture2D heightTexture_;
         //Texture2D colorTexture_;
         Texture2D normalTexture_;
 
         Texture2D WaterTex, GrassTex, RockTex, SnowTex, WaterNormTex, GrassNormTex, RockNormTex, SnowNormTex;
 
         Texture2D AlphaMap;
 
         const int MapShift = 11;
         const int MapSize = (1 << MapShift);
         const int MapAnd = (MapSize - 1);
 
         const float SeaThreshold = 0.8f;
         const float HillsThreshold = 0.85f;
         const float MountainThreshold = 0.9f;
         const float SnowThreshold = 0.999f;
         const float NormalMapStrength = 4.0f;
 
         public float rotationSpeedX { get; set; }
         public float rotationSpeedY { get; set; }
         public float rotationSpeedZ { get; set; }
 
         /// <summary>
         /// Constructs a new Planet,
         /// with the specified size and tessellation level.
         /// </summary>
         public cpuPerlinPlanet(int seed, Controllers.Lights.LightTypes.genericLight Light, float diameter, cAtmosphere aAtmosphere)
             : base()
         {
 
             //, Game game, GraphicsDevice GraphicsDevice
             Seed = seed;
             //_game = game;
             PlanetSize = diameter;
             Atmosphere = aAtmosphere;
             //_GraphicsDevice = GraphicsDevice;
             _Light = Light;
 
             position = new MathLib.Vector3_64(0d, 0d, 0d);
             rotation = new Quaternion(0, 0, 0, 1);
             scale = new Vector3(diameter, diameter, diameter);
         }
 
         /// <summary>
         /// Load the content
         /// </summary>
         public override void LoadContent()
         {
             // Create the perlin texture for the planet
             GenerateTextures(Seed);
 
             shader = GameEngine.mContentManager.Load<Effect>("Content/Shaders/Mesh/PlanetShader");
             DepthAndNormalsEffect = GameEngine.mContentManager.Load<Effect>("Content/Shaders/Mesh/PlanetNormalsDepth");
 
             //PlanetTex = colorTexture_;
             PlanetNrmTex = normalTexture_;
             PlanetSpecTex = GameEngine.mContentManager.Load<Texture2D>("Content/Textures/Planet/earthmap10k_SPEC");
 
             WaterTex = GameEngine.mContentManager.Load<Texture2D>("Content/Textures/Planet/Generic/EarthWater");
             GrassTex = GameEngine.mContentManager.Load<Texture2D>("Content/Textures/Planet/Generic/EarthGrass");
             RockTex = GameEngine.mContentManager.Load<Texture2D>("Content/Textures/Planet/Generic/EarthRock");
             SnowTex = GameEngine.mContentManager.Load<Texture2D>("Content/Textures/Planet/Generic/EarthSnow");
 
             WaterNormTex = GameEngine.mContentManager.Load<Texture2D>("Content/Textures/Planet/Generic/EarthWater_NRM");
             GrassNormTex = GameEngine.mContentManager.Load<Texture2D>("Content/Textures/Planet/Generic/EarthGrass_NRM");
             RockNormTex = GameEngine.mContentManager.Load<Texture2D>("Content/Textures/Planet/Generic/EarthRock_NRM");
             SnowNormTex = GameEngine.mContentManager.Load<Texture2D>("Content/Textures/Planet/Generic/EarthSnow_NRM");
 
             PlanetMesh = GameEngine.mContentManager.Load<Model>("Content/Models/Planet50k");
 
             CloudTex = Atmosphere.CloudTex;
             gTexture = Atmosphere.texture;
 
             // Set the depth buffer
             //this.cachedBuffer = new DepthStencilBuffer(shader.GraphicsDevice, Core.getInstance().GraphicsDevice.Viewport.Width, Core.getInstance().GraphicsDevice.Viewport.Height, DepthFormat.Depth16);
         }
 
         /// <summary>
         /// Generate the textures for the perlin planet
         /// </summary>
         /// <param name="seed"></param>
         private void GenerateTextures(int seed)
         {
             Random rand = new Random(seed);
 
             //  generate a height map
             float[] h = new float[MapSize * MapSize];
             //  use midpoint displacement in a breadth-first manner
             float distance = 1.0f;
             int countdown = 2;
             for (int generation = 0; generation <= MapShift; ++generation)
             {
                 //  for each generation, perturb the lower-right corner of successively 
                 //  smaller divided squares
                 int add = (1 << (MapShift - generation));
                 for (int y = add; y <= MapSize; y += add)
                 {
                     for (int x = add; x <= MapSize; x += add)
                     {
                         h[((y & MapAnd) * MapSize) + (x & MapAnd)] += (generation == 0) ? 0.5f : ((float)(rand.NextDouble() - 0.5) * distance);
                     }
                 }
                 if (generation < MapShift)
                 {
                     System.Diagnostics.Debug.Assert(add > 1);
                     int off = add >> 1;
                     //  average the edges, and the midpoint of the square
                     for (int y = 0; y < MapSize; y += add)
                     {
                         for (int x = 0; x < MapSize; x += add)
                         {
                             float h00 = h[((y & MapAnd) * MapSize) + (x & MapAnd)];
                             float h01 = h[((y & MapAnd) * MapSize) + ((x + add) & MapAnd)];
                             float h10 = h[(((y + add) & MapAnd) * MapSize) + (x & MapAnd)];
                             float h11 = h[(((y + add) & MapAnd) * MapSize) + ((x + add) & MapAnd)];
                             h[((y & MapAnd) * MapSize) + ((x + off) & MapAnd)] = (h00 + h01) * 0.5f;
                             h[(((y + off) & MapAnd) * MapSize) + (x & MapAnd)] = (h00 + h10) * 0.5f;
                             h[(((y + add) & MapAnd) * MapSize) + ((x + off) & MapAnd)] = (h10 + h11) * 0.5f;
                             h[(((y + off) & MapAnd) * MapSize) + ((x + add) & MapAnd)] = (h01 + h11) * 0.5f;
                             h[(((y + off) & MapAnd) * MapSize) + ((x + off) & MapAnd)] = (h00 + h01 + h10 + h11) * 0.25f;
                         }
                     }
                 }
                 if (countdown > 0)
                     --countdown;
                 else
                     distance = distance * 0.5f;
             }
 
             //  now, filter the edges of the texture because the poles are smaller area than the equator
             for (int i = 0; i < MapSize / 4; ++i)
             {
                 float f = 0;
                 int bins = i;
                 float weight = 1 - i / (MapSize / 4);
                 int curbin = 0;
                 int curcnt = 0;
                 int binoffset = 0;
                 int off = i * MapSize;
                 for (int j = 0; j < MapSize; ++j)
                 {
                     int bin = j * bins / MapSize;
                     if (bin != curbin)
                     {
                         f /= curcnt;
                         for (int q = binoffset; q < j; ++q)
                             h[off + q] = h[off + q] * (1 - weight) + f * weight;
                         f = 0;
                         curcnt = 0;
                         curbin = bin;
                         binoffset = j;
                     }
                     f += h[off + j];
                     ++curcnt;
                 }
                 f /= curcnt;
                 for (int q = binoffset; q < MapSize; ++q)
                     h[off + q] = h[off + q] * (1 - weight) + f * weight;
                 off = (MapSize - i - 1) * MapSize;
                 f = 0;
                 curbin = 0;
                 curcnt = 0;
                 binoffset = 0;
                 for (int j = 0; j < MapSize; ++j)
                 {
                     int bin = j * bins / MapSize;
                     if (bin != curbin)
                     {
                         f /= curcnt;
                         for (int q = binoffset; q < j; ++q)
                             h[off + q] = h[off + q] * (1 - weight) + f * weight;
                         f = 0;
                         curcnt = 0;
                         curbin = bin;
                         binoffset = j;
                     }
                     f += h[off + j];
                     ++curcnt;
                 }
                 f /= curcnt;
                 for (int q = binoffset; q < MapSize; ++q)
                     h[off + q] = h[off + q] * (1 - weight) + f * weight;
             }
 
             Color[] c = new Color[MapSize * MapSize];
             Color[] c2 = new Color[MapSize * MapSize];
             
             for (int y = 0; y < MapSize; ++y)
                 for (int x = 0; x < MapSize; ++x)
                 {
                     float height = h[y * MapSize + x];
 
                     if (height < SeaThreshold)
                         c2[y * MapSize + x].R = 255;
                     else c2[y * MapSize + x].R = 0;
 
                     if (height >= SeaThreshold && height < HillsThreshold)
                         c2[y * MapSize + x].G = 255;
                     else c2[y * MapSize + x].G = 0;
 
                     if (height >= HillsThreshold && height < MountainThreshold)
                         c2[y * MapSize + x].B = 255;
                     else c2[y * MapSize + x].B = 0;
 
                     if (height >= SnowThreshold)
                         c2[y * MapSize + x].A = 255;
                     else c2[y * MapSize + x].A = 0;
                     c[y * MapSize + x] = HeightToColor(h[y * MapSize + x], y);
                 }
             
             //if (colorTexture_ != null)
             //    colorTexture_.Dispose();
             
             //colorTexture_ = new Texture2D(_game.GraphicsDevice, MapSize, MapSize, 0, TextureUsage.AutoGenerateMipMap, SurfaceFormat.Color);
             //colorTexture_.SetData<Color>(c);
 
             if (AlphaMap != null)
                 AlphaMap.Dispose();
 
             AlphaMap = new Texture2D(GameEngine.mGraphicsDevice, MapSize, MapSize, false, SurfaceFormat.Color);
             AlphaMap.SetData<Color>(c2);
 
             for (int y = 0; y < MapSize; ++y)
                 for (int x = 0; x < MapSize; ++x)
                     c[y * MapSize + x] = CalcNormal(ref h, x, y);
             
             if (normalTexture_ != null)
                 normalTexture_.Dispose();
 
             normalTexture_ = new Texture2D(GameEngine.mGraphicsDevice, MapSize, MapSize, false, SurfaceFormat.Color);
             
             normalTexture_.SetData<Color>(c);
 
             PostprocessPipeline.PostProcessComponent Blur = new PostprocessPipeline.GaussBlurComponent(_Light);
             Blur.LoadContent();
             Blur.Draw(new GameTime());
             AlphaMap = Blur.outputRT.RenderTarget;
         }
 
         /// <summary>
         /// Calculate the normals
         /// </summary>
         /// <param name="h">Height data</param>
         /// <param name="x">X position</param>
         /// <param name="y">Y position</param>
         /// <returns></returns>
         private Color CalcNormal(ref float[] h, int x, int y)
         {
             float du = (h[x + y * MapSize] - h[((x + 1) & MapAnd) + y * MapSize]) * NormalMapStrength;
             float dv = (h[x + y * MapSize] - h[x + ((y + 1) & MapAnd) * MapSize]) * NormalMapStrength;
             float z = (float)Math.Abs(du) + Math.Abs(dv);
             if (z > 1)
             {
                 du /= z;
                 dv /= z;
             }
             float dw = (float)Math.Sqrt(1.0f - du * du - dv * dv);
             return new Color(new Vector3(du * 0.5f + 0.5f, dv * 0.5f + 0.5f, dw));
         }
 
         /// <summary>
         /// Create a color based on the height
         /// </summary>
         /// <param name="h"></param>
         /// <param name="latitude"></param>
         /// <returns>Color</returns>
         private Color HeightToColor(float h, int latitude)
         {
             float latScale = (100.0f + Math.Abs(latitude - MapSize / 2)) / 200.0f;
             float w;
             if (h < SeaThreshold)
             {
                 w = SeaThreshold - h;
                 if (w > 1) w = 1;
                 return Color.Lerp(Color.Blue, Color.DarkBlue, w);
             }
             //  make things colder outside of the equator
             h = SeaThreshold + (h - SeaThreshold) * latScale;
             if (h < MountainThreshold)
             {
                 w = (MountainThreshold - h) / (MountainThreshold - SeaThreshold);
                 return Color.Lerp(Color.DarkGreen, Color.DarkKhaki, w);
             }
             if (h < SnowThreshold)
             {
                 w = (SnowThreshold - h) / (SnowThreshold - MountainThreshold);
                 return Color.Lerp(Color.LightGray, Color.DarkGray, w);
             }
             w = h - SnowThreshold;
             if (w > 0.5f) w = 0.5f;
             return Color.Lerp(Color.LightCyan, Color.White, w + 0.5f);
         }
 
         /// <summary>
         /// Update the rotation of the planet
         /// </summary>
         /// <param name="cameraPosition"></param>
         /// <param name="gameTime"></param>
         internal override void Update(GameTime gameTime)
         {
             Vector3 axisX = new Vector3(1, 0, 0);
             Vector3 axisY = new Vector3(0, 1, 0);
             Vector3 axisZ = new Vector3(0, 0, 1);
             
             axisX = Vector3.Transform(axisX, Matrix.CreateFromQuaternion(this.rotation));
             axisY = Vector3.Transform(axisY, Matrix.CreateFromQuaternion(this.rotation));
             axisY = Vector3.Transform(axisZ, Matrix.CreateFromQuaternion(this.rotation));
 
             this.rotation = Quaternion.Normalize(Quaternion.CreateFromAxisAngle(axisX, this.rotationSpeedX * gameTime.ElapsedGameTime.Milliseconds) * Quaternion.CreateFromAxisAngle(axisY, this.rotationSpeedY * gameTime.ElapsedGameTime.Milliseconds) * Quaternion.CreateFromAxisAngle(axisZ, this.rotationSpeedZ * gameTime.ElapsedGameTime.Milliseconds) * this.rotation);
 
             base.Update(gameTime);
         }
 
         /// <summary>
         /// Draws the planet, using the specified effect. Unlike the other
         /// Draw overload where you just specify the world/view/projection matrices
         /// and color, this method does not set any renderstates, so you must make
         /// sure all states are set to sensible values before you call it.
         /// </summary>
         public override void Draw(GameTime gameTime)
         {
             // Set important renderstates.
             //RenderState renderState = shader.GraphicsDevice.RenderState;
             //renderState.AlphaTestEnable = false;
             //Set renderstates for opaque rendering.
             //renderState.AlphaBlendEnable = false;
             //renderState.CullMode = CullMode.CullCounterClockwiseFace;
 
             // Updated renderstates for stencil buffer
             //renderState.DepthBufferEnable = true;
             //renderState.DepthBufferFunction = CompareFunction.LessEqual;
             //renderState.DepthBufferWriteEnable = true;
 
             // Cache the current depth buffer  
             //this.tmpBuffer = shader.GraphicsDevice.DepthStencilBuffer;
 
             //shader.GraphicsDevice.DepthStencilBuffer = this.cachedBuffer; //new DepthStencilBuffer(shader.GraphicsDevice, Core.getInstance().GraphicsDevice.Viewport.Width, Core.getInstance().GraphicsDevice.Viewport.Height, DepthFormat.Depth16);
             //shader.GraphicsDevice.DepthStencilBuffer = new DepthStencilBuffer(shader.GraphicsDevice, Core.getInstance().GraphicsDevice.Viewport.Width, Core.getInstance().GraphicsDevice.Viewport.Height, DepthFormat.Depth15Stencil1);  
             
             // Set our custom depth buffer  
             //shader.GraphicsDevice.DepthStencilBuffer = shadowDepthBuffer;  
 
             shader.Parameters["World"].SetValue(this.myWorldMatrix);
             shader.Parameters["WorldIT"].SetValue(this.myWorldInverseTranspose);
             shader.Parameters["View"].SetValue(GameEngine.mCameraManager.activeCamera.myViewMatrix);
             shader.Parameters["Projection"].SetValue(GameEngine.mCameraManager.activeCamera.myProjectionMatrix);
             //shader.Parameters["PlanetTex"].SetValue(PlanetTex);
             shader.Parameters["Splat1"].SetValue(WaterTex);
             shader.Parameters["Splat2"].SetValue(GrassTex);
             shader.Parameters["Splat3"].SetValue(RockTex);
             shader.Parameters["Splat4"].SetValue(SnowTex);
             shader.Parameters["AlphaMap"].SetValue(AlphaMap);
             shader.Parameters["CloudDiffuse"].SetValue(CloudTex);
             shader.Parameters["gTex"].SetValue(gTexture);
             shader.Parameters["ReflectionMap"].SetValue(PlanetSpecTex);
             shader.Parameters["AtmosphereHeight"].SetValue(Atmosphere.AtmosphereSize);
             shader.Parameters["elaspedtime"].SetValue((float)gameTime.TotalGameTime.TotalSeconds * 3);
             shader.Parameters["LightPos"].SetValue(_Light.position_32);
             shader.Parameters["FarPlane"].SetValue(GameEngine.mCameraManager.activeCamera.maximumDepth);
 
             Texture2D LightBuffer = LightPrePass.Manager.GetLightBuffer();
             shader.Parameters["LightBuffer"].SetValue(LightBuffer);
 
             Vector2 HalfPixel = new Vector2
             (
                 0.5f / (float)LightPrePass.Manager.LightingBuffer.ScreenSize.X,
                 0.5f / (float)LightPrePass.Manager.LightingBuffer.ScreenSize.Y
             );
             shader.Parameters["HalfPixel"].SetValue(HalfPixel);
 
             // Draw the model. A model can have multiple meshes, so loop.
             foreach (ModelMesh mesh in PlanetMesh.Meshes)
             {
                 foreach (ModelMeshPart part in mesh.MeshParts)
                 {
                     part.Effect = shader;
                 }
 
                 // Draw the mesh, using the effect set above.
                 mesh.Draw();
             }
 
             base.Draw(gameTime);
 
             // Set the buffer back to it's original
             //shader.GraphicsDevice.DepthStencilBuffer = tmpBuffer;
         }
 
         /// <summary>
         /// Draw the planet
         /// </summary>
         /// <param name="gameTime"></param>
         /// <param name="effect"></param>
         /// <param name="WorldViewProjection"></param>
         public override void Draw(GameTime gameTime, Effect effect, Matrix WorldViewProjection)
         {
             effect.Parameters["WorldViewProj"].SetValue(WorldViewProjection);
 
             // Draw the model. A model can have multiple meshes, so loop.
             foreach (ModelMesh mesh in PlanetMesh.Meshes)
             {
                 foreach (ModelMeshPart part in mesh.MeshParts)
                 {
                     part.Effect = effect;
                 }
 
                 // Draw the mesh, using the effect set above.
                 mesh.Draw();
             }
 
             base.Draw(gameTime);
         }
 
         public void DrawNormalsAndDepth()
         {
             DepthAndNormalsEffect.Parameters["World"].SetValue(myWorldMatrix);
             DepthAndNormalsEffect.Parameters["WorldIT"].SetValue(this.myWorldInverseTranspose);
             DepthAndNormalsEffect.Parameters["View"].SetValue(GameEngine.mCameraManager.activeCamera.myViewMatrix);
             DepthAndNormalsEffect.Parameters["Projection"].SetValue(GameEngine.mCameraManager.activeCamera.myProjectionMatrix);
             DepthAndNormalsEffect.Parameters["FarPlane"].SetValue(GameEngine.mCameraManager.activeCamera.maximumDepth);
             DepthAndNormalsEffect.Parameters["Splat1Norm"].SetValue(WaterNormTex);
             DepthAndNormalsEffect.Parameters["Splat2Norm"].SetValue(GrassNormTex);
             DepthAndNormalsEffect.Parameters["Splat3Norm"].SetValue(RockNormTex);
             DepthAndNormalsEffect.Parameters["Splat4Norm"].SetValue(SnowNormTex);
             DepthAndNormalsEffect.Parameters["AlphaMap"].SetValue(AlphaMap);
 
             // Draw the model. A model can have multiple meshes, so loop.
             foreach (ModelMesh mesh in PlanetMesh.Meshes)
             {
                 foreach (ModelMeshPart part in mesh.MeshParts)
                 {
                     part.Effect = DepthAndNormalsEffect;
                 }
 
                 // Draw the mesh, using the effect set above.
                 mesh.Draw();
             }
         }
     }
 }
 

Hopefully this is more useful for you, and good luck!

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
4

Answer by Kos-Dvornik · Mar 03, 2014 at 08:08 AM

With sources: http://kostiantyn-dvornik.blogspot.com/2014/02/huge-amazing-unity-terrain-tutorial.html

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

14 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Procedural planet surface 0 Answers

Procedural Cave Generation Can´t understand?? 0 Answers

Can you use the superformula in unity? 0 Answers

Life size planets (making a planet i can land on) 1 Answer

Things that I don't get in Procedural Cave generation Tutorial 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges