Search Unity

Unity terrain : how to achieve a udk or cryengine look?

Discussion in 'Editor & General Support' started by cod, Feb 2, 2012.

  1. cod

    cod

    Joined:
    Nov 26, 2011
    Posts:
    267
    Hi all :D,I posted this thread because I'd like to share(and maybe improve) a custom terrain shader. As u can understand from the title, I'd like to achieve a terrain like battlefield 3 or udk engine. Before typing please read this topic
    http://udn.epicgames.com/Three/TerrainAdvancedTextures.html

    It's really interesting, but I'd like to add normal maps to my terrain, as seen there

    http://forums.epicgames.com/threads/722288-Advanced-Terrain-Texturing-downsampling?

    Note the normal map(I think) :


    What's that? a normal map and how can I make one like this in unity?

    ok, now I'll post my code.
    NOTE this code has not been created by me. I modified the shader so that u can have a better quality over the terrain and add a normal map to the terrain
    Code (csharp):
    1. /* Code provided by Chris Morris of Six Times Nothing (http://www.sixtimesnothing.com) */
    2. /* Free to use and modify  */
    3.  
    4.  
    5. Shader "Hidden/TerrainEngine/Splatmap/Lightmap-FirstPass" {
    6. Properties {
    7.     _Control ("Control (RGBA)", 2D) = "red" {}
    8.     _Splat3 ("Layer 3 (A)", 2D) = "white" {}
    9.     _Splat2 ("Layer 2 (B)", 2D) = "white" {}
    10.     _Splat1 ("Layer 1 (G)", 2D) = "white" {}
    11.     _Splat0 ("Layer 0 (R)", 2D) = "white" {}
    12.     // used in fallback on old cards
    13.     _MainTex ("BaseMap (RGB)", 2D) = "white" {}
    14.     _Color ("Main Color", Color) = (1,1,1,1)
    15. }
    16.  
    17. SubShader {
    18.     Tags {
    19.         "SplatCount" = "4"
    20.         "Queue" = "Geometry-100"
    21.         "RenderType" = "Opaque"
    22.     }
    23.  
    24. CGPROGRAM
    25. #pragma surface surf BlinnPhong vertex:vert
    26. #pragma target 3.0
    27. #include "UnityCG.cginc"
    28.  
    29. struct Input {
    30.     //float3 worldPos;
    31.     float2 uv_Control : TEXCOORD0;
    32.     float2 uv_Splat0 : TEXCOORD1;
    33.     float2 uv_Splat1 : TEXCOORD2;
    34.     float2 uv_Splat2 : TEXCOORD3;
    35.     float2 uv_Splat3 : TEXCOORD4;
    36.     //float2 uv_Splat4 : TEXCOORD5;
    37.    
    38.     //fixed4 color : COLOR;
    39.     float2 uv_BumpMap : TEXCOORD0;
    40.     float3 viewDir;
    41.    
    42.    
    43. };
    44.  
    45. // Supply the shader with tangents for the terrain
    46. void vert (inout appdata_full v) {
    47.  
    48.     // A general tangent estimation
    49.     float3 T1 = float3(1, 0, 1);
    50.     float3 Bi = cross(T1, v.normal);
    51.     float3 newTangent = cross(v.normal, Bi);
    52.     normalize(newTangent);
    53.     v.tangent.xyz = newTangent.xyz;
    54.     if (dot(cross(v.normal,newTangent),Bi) < 0)
    55.     v.tangent.w = -1.0f;
    56.     else
    57.         v.tangent.w = 1.0f;
    58. }
    59.  
    60. sampler2D _Control, _ParallaxMap;
    61. sampler2D _BumpMap0, _BumpMap1, _BumpMap2, _BumpMap3 , _BumpMap4, _BumpTerrain;
    62. sampler2D _Splat0,_Splat1,_Splat2,_Splat3, _Splat4;
    63. float _Tile0, _Tile1, _Tile2, _Tile3, _Tile4, _TerrainX, _TerrainZ, _TileX, _TileY;
    64.  
    65. void surf (Input IN, inout SurfaceOutput o) {
    66.     half4 splat_control = tex2D (_Control, IN.uv_Control);
    67.     half3 col;
    68.     half3 norm;
    69.    
    70. // first texture which is usually some kind of rock texture gets mixed with itself
    71. // see: http://forum.unity3d.com/threads/116509-Improved-Terrain-Texture-Tiling    
    72.     norm =  UnpackNormal(tex2D(_BumpTerrain, float2(IN.uv_Control.x * _TileX, IN.uv_Control.y * _TileY))) * UnpackNormal(tex2D(_BumpTerrain, float2(IN.uv_Control.x * -0.5, IN.uv_Control.y * -0.5)));
    73.     col = splat_control.r * tex2D (_Splat0, IN.uv_Splat0).rgb * tex2D (_Splat0, IN.uv_Splat0 * -0.125).rgb * 3;
    74.     norm += splat_control.r * UnpackNormal(tex2D(_BumpMap0, float2(IN.uv_Control.x * (_TerrainX/_Tile0), IN.uv_Control.y * (_TerrainZ/_Tile0))));
    75.  
    76.     col += splat_control.g * tex2D (_Splat1, IN.uv_Splat1).rgb * tex2D (_Splat1, IN.uv_Splat1 * -0.125).rgb * 3;
    77.     norm += splat_control.g * UnpackNormal(tex2D(_BumpMap1, float2(IN.uv_Control.x * (_TerrainX/_Tile1), IN.uv_Control.y * (_TerrainZ/_Tile1))));
    78.    
    79.     col += splat_control.b * tex2D (_Splat2, IN.uv_Splat2).rgb * tex2D (_Splat2, IN.uv_Splat2 * -0.125).rgb * 1;
    80.     norm += splat_control.b * UnpackNormal(tex2D(_BumpMap2, float2(IN.uv_Control.x * (_TerrainX/_Tile2), IN.uv_Control.y * (_TerrainZ/_Tile2))));
    81.    
    82.     col += splat_control.a * tex2D (_Splat3, IN.uv_Splat3).rgb * tex2D (_Splat3, IN.uv_Splat3 * -0.125).rgb * 0.9;
    83.     norm += splat_control.a * UnpackNormal(tex2D(_BumpMap3, float2(IN.uv_Control.x * (_TerrainX/_Tile3), IN.uv_Control.y * (_TerrainZ/_Tile3))));
    84.    
    85.     o.Albedo = col;
    86.     o.Normal = norm;
    87.    
    88. }
    89. ENDCG  
    90. }
    91.  
    92. // Fallback to Diffuse
    93. Fallback "Diffuse"
    94. }

    And the script to attach to the terrain in order to add normal maps :

    Code (csharp):
    1.  
    2.  
    3. using UnityEngine;
    4.  
    5. using System.Collections;
    6.  
    7. [ExecuteInEditMode]
    8.  
    9. public class CustomTerrainScriptAtsV2 : MonoBehaviour {
    10.  
    11.     public Texture2D BumpTerrain;
    12.  
    13.     public float TileX;
    14.  
    15.     public float TileY;
    16.  
    17.     public Texture2D[] Bump;
    18.  
    19.     public float[] Tile;
    20.  
    21.     public float terrainSizeX;
    22.  
    23.     public float terrainSizeZ;
    24.  
    25.    
    26.  
    27.     void Update () {
    28.  
    29.         //Terrain.activeTerrain.heightmapPixelError = 1;
    30.  
    31.         //Terrain.activeTerrain.basemapDistance = 40000;
    32.  
    33.         //Terrain.activeTerrain.detailObjectDistance = 4000;
    34.  
    35.  
    36.  
    37.        
    38.  
    39.         Terrain terrainComp = (Terrain)GetComponent(typeof(Terrain));
    40.  
    41.         Shader.SetGlobalTexture("_BumpTerrain" , BumpTerrain);
    42.  
    43.         Shader.SetGlobalFloat("_TileX", TileX);
    44.  
    45.         Shader.SetGlobalFloat("_TileY", TileY);
    46.  
    47.         for  (int i = 0; i < Bump.Length; i++){
    48.  
    49.             Shader.SetGlobalTexture("_BumpMap"+i.ToString(), Bump[i]);
    50.  
    51.             Shader.SetGlobalFloat("_Tile"+i.ToString(), Tile[i]);
    52.  
    53.            
    54.  
    55.         }
    56.  
    57.         /*
    58.  
    59.         if(Bump0)
    60.  
    61.             Shader.SetGlobalTexture("_BumpMap0", Bump0);
    62.  
    63.        
    64.  
    65.         if(Bump1)
    66.  
    67.             Shader.SetGlobalTexture("_BumpMap1", Bump1);
    68.  
    69.        
    70.  
    71.         if(Bump2)
    72.  
    73.             Shader.SetGlobalTexture("_BumpMap2", Bump2);
    74.  
    75.        
    76.  
    77.         if(Bump3)
    78.  
    79.             Shader.SetGlobalTexture("_BumpMap3", Bump3);
    80.  
    81.        
    82.  
    83.         Shader.SetGlobalFloat("_Tile0", Tile0);
    84.  
    85.         Shader.SetGlobalFloat("_Tile1", Tile1);
    86.  
    87.         Shader.SetGlobalFloat("_Tile2", Tile2);
    88.  
    89.         Shader.SetGlobalFloat("_Tile3", Tile3);
    90.  
    91.         */
    92.  
    93.         terrainSizeX = terrainComp.terrainData.size.x;
    94.  
    95.         terrainSizeZ = terrainComp.terrainData.size.z;
    96.  
    97.        
    98.  
    99.         Shader.SetGlobalFloat("_TerrainX", terrainSizeX);
    100.  
    101.         Shader.SetGlobalFloat("_TerrainZ", terrainSizeZ);
    102.  
    103.     }
    104.  
    105.  
    106.  
    107. }
    108.  
    109.  
    I hope this will be helpful to u and I'd like to have some feedback and answer.
    Thanks for your time and sorry for my english :D
     
  2. cod

    cod

    Joined:
    Nov 26, 2011
    Posts:
    267
  3. Wolfos

    Wolfos

    Joined:
    Mar 17, 2011
    Posts:
    951
    Both normal maps and parallax maps are supported:
    http://blog.sixtimesnothing.com/2010/11/displacement-mapping-with-unitys-built-in-terrain/

    However, this is very buggy on Mac OS-X. I solved this by using the Substance Terrain tool shader from the asset store in combination with the script from SixTimesNothing, which fixes the problems AS LONG as you use only 4 textures on a single terrain. If you use more, artifacts will occur.

    Also, Unity is looking into shaders on terrain:
    http://feedback.unity3d.com/forums/15792-unity/suggestions/375921-graphics-shaders-on-terrain
    And into road/river splines:
    http://feedback.unity3d.com/forums/15792-unity/suggestions/176095-terrain-road-river-splines
     
    Last edited: Feb 2, 2012
  4. TheCasual

    TheCasual

    Joined:
    Sep 30, 2010
    Posts:
    1,286
    Not to knock Unity , im a fan for sure , but, its true , Unity terrain is pretty bad IMO. Me and my partner develop all our terrains in software, and generally utilize custom shaders in engine.

    Again , i love Unity ,came from UDK to unity because of the ease and flow of scripting to the engine, where UDK was a pain in the ass without ten others to assist. But the terrains gotta get a serious rework before it will ever be up to par of the other engines.
     
  5. Wolfos

    Wolfos

    Joined:
    Mar 17, 2011
    Posts:
    951
    Terrains are my top 5 of complaints about Unity. I'd rather them starting over with a Voxel terrain than improving the current one.
     
  6. cod

    cod

    Joined:
    Nov 26, 2011
    Posts:
    267
    u'r right, but how can I get a effect like this on my terrain?

    instead this

    Is there a way(modifying my shader) to achieve this result?
     
  7. Demostenes

    Demostenes

    Joined:
    Sep 10, 2010
    Posts:
    1,106
  8. cod

    cod

    Joined:
    Nov 26, 2011
    Posts:
    267
    Come on, any hint?
     
  9. cod

    cod

    Joined:
    Nov 26, 2011
    Posts:
    267
    right now I've achieved this amazing result :
    $terrain.png

    BTW I have a serious problem : It doesn't look very well if seen near >.<'
    $terrain2.jpg
     
  10. Demostenes

    Demostenes

    Joined:
    Sep 10, 2010
    Posts:
    1,106
    Generally terrain engine is obsolete crap. You can modify shaders somehow, but there are limited parametres and so impossible to do something really good. There are various hacks (as you presented), each has advantages and disadvantages.

    Your problem is probably in bad texture.
     
  11. TheCasual

    TheCasual

    Joined:
    Sep 30, 2010
    Posts:
    1,286
    Demonstenes has a very harsh way of coming across sometimes.... but in this particular case, i couldnt agree more.
     
  12. larsbertram1

    larsbertram1

    Joined:
    Oct 7, 2008
    Posts:
    6,900
    hi,

    like you can mix diffuse maps on the terrain you also can mix uv-scaled versions of bumpmaps. or even add one bump map covering the whole terrain like shown in your unreal example.

    have a look at: http://bit.ly/zFLUEa
    the diffuse and normal map of the rock texture is mixed in different uv scales.

    lars
     
  13. cod

    cod

    Joined:
    Nov 26, 2011
    Posts:
    267
    tank u man for ur reply. I have to thak u because I modifyed your terrain shder and right now it looks awesome!! BTW there'r a lot of thing I'd like to improve, such as the details and the bumpmaps on the terrain.
    Do u know how to rotate textures on the terrain as seen in the article from UDN? Then could u explain me how to use a addpass so that I can only apply uv-scaled versions of bumpmaps only on some mountains?


    Thank u and sorry for all those questions :), right now I'm not at home, but this evening I'll post some nice pictures :D


    PS sorry but terrain textures aren't so good, they look as if u have built the game with fastest graphical option
     
    Last edited: Feb 7, 2012
  14. larvantholos

    larvantholos

    Joined:
    Oct 29, 2009
    Posts:
    668
    btw, a simple thing you can do is select the textures themselves, and modify the ansio levels in the texture properties, this can help you achieve a shaper result from different viewing distances, at the cost of some performance.
     
  15. cod

    cod

    Joined:
    Nov 26, 2011
    Posts:
    267
    Some pictures :
    $terra1.jpg
    $terra.jpg
    $terra2.jpg
     
  16. larsbertram1

    larsbertram1

    Joined:
    Oct 7, 2008
    Posts:
    6,900
    i think you mean the rock texture in the webplayer? if so: this is due to mixing the texture with itself at an upscaled (therefore lowres) version of itself. depending on your texture and some other factors like possible view distances you can tweak the ratio between original (highres) texture and its upscaled version. in the webplayer i use .5/.5 which gives you very nice results for far views (where the upscaled version affects the look much more than the highres version as details get lost) but not so nice results on close views.
    but you can strengthen the highres version e.g. mixing them like: .75/.35

    lars
     
  17. Mark-Davis

    Mark-Davis

    Joined:
    Jun 21, 2011
    Posts:
    156
    Have you seen Voxelform by chance? It's not a replacement for all use cases, but you can use it for organic deformable multi-material voxel terrain in Unity.

    Here's an example of voxel terrain using a blend of a simple triplanar shader and a modified 3D Perlin noise shader with a few major optimizations. The noise permeates the terrain volumetrically and you can see that as you tunnel through it.


    This is an example of multi-material terrain using more advanced triplanar shaders with normal and specular support among other things.


    Playable in-browser demos here.

    Videos on YouTube:

    Voxelform 2.0 - Caves Demo


    Voxelform 2.0 - Editor