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

Hi all :smile:,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 provided by Chris Morris of Six Times Nothing (http://www.sixtimesnothing.com) */
/* Free to use and modify  */


Shader "Hidden/TerrainEngine/Splatmap/Lightmap-FirstPass" {
Properties {
	_Control ("Control (RGBA)", 2D) = "red" {}
	_Splat3 ("Layer 3 (A)", 2D) = "white" {}
	_Splat2 ("Layer 2 (B)", 2D) = "white" {}
	_Splat1 ("Layer 1 (G)", 2D) = "white" {}
	_Splat0 ("Layer 0 (R)", 2D) = "white" {}
	// used in fallback on old cards
	_MainTex ("BaseMap (RGB)", 2D) = "white" {}
	_Color ("Main Color", Color) = (1,1,1,1)
}

SubShader {
	Tags {
		"SplatCount" = "4"
		"Queue" = "Geometry-100"
		"RenderType" = "Opaque"
	}

CGPROGRAM
#pragma surface surf BlinnPhong vertex:vert
#pragma target 3.0
#include "UnityCG.cginc"

struct Input {
	//float3 worldPos;
	float2 uv_Control : TEXCOORD0;
	float2 uv_Splat0 : TEXCOORD1;
	float2 uv_Splat1 : TEXCOORD2;
	float2 uv_Splat2 : TEXCOORD3;
	float2 uv_Splat3 : TEXCOORD4;
	//float2 uv_Splat4 : TEXCOORD5;
	
	//fixed4 color : COLOR;
	float2 uv_BumpMap : TEXCOORD0;
	float3 viewDir;
	
	
};

// Supply the shader with tangents for the terrain
void vert (inout appdata_full v) {

	// A general tangent estimation	
	float3 T1 = float3(1, 0, 1);
	float3 Bi = cross(T1, v.normal);
	float3 newTangent = cross(v.normal, Bi);
	normalize(newTangent);
	v.tangent.xyz = newTangent.xyz;
	if (dot(cross(v.normal,newTangent),Bi) < 0)
	v.tangent.w = -1.0f;
	else
		v.tangent.w = 1.0f;
}

sampler2D _Control, _ParallaxMap;
sampler2D _BumpMap0, _BumpMap1, _BumpMap2, _BumpMap3 , _BumpMap4, _BumpTerrain;
sampler2D _Splat0,_Splat1,_Splat2,_Splat3, _Splat4;
float _Tile0, _Tile1, _Tile2, _Tile3, _Tile4, _TerrainX, _TerrainZ, _TileX, _TileY;

void surf (Input IN, inout SurfaceOutput o) {
	half4 splat_control = tex2D (_Control, IN.uv_Control);
	half3 col;
	half3 norm;
	
// first texture which is usually some kind of rock texture gets mixed with itself
// see: http://forum.unity3d.com/threads/116509-Improved-Terrain-Texture-Tiling 	
	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)));
	col = splat_control.r * tex2D (_Splat0, IN.uv_Splat0).rgb * tex2D (_Splat0, IN.uv_Splat0 * -0.125).rgb * 3;
	norm += splat_control.r * UnpackNormal(tex2D(_BumpMap0, float2(IN.uv_Control.x * (_TerrainX/_Tile0), IN.uv_Control.y * (_TerrainZ/_Tile0))));

	col += splat_control.g * tex2D (_Splat1, IN.uv_Splat1).rgb * tex2D (_Splat1, IN.uv_Splat1 * -0.125).rgb * 3;
	norm += splat_control.g * UnpackNormal(tex2D(_BumpMap1, float2(IN.uv_Control.x * (_TerrainX/_Tile1), IN.uv_Control.y * (_TerrainZ/_Tile1))));
	
	col += splat_control.b * tex2D (_Splat2, IN.uv_Splat2).rgb * tex2D (_Splat2, IN.uv_Splat2 * -0.125).rgb * 1;
	norm += splat_control.b * UnpackNormal(tex2D(_BumpMap2, float2(IN.uv_Control.x * (_TerrainX/_Tile2), IN.uv_Control.y * (_TerrainZ/_Tile2))));
	
	col += splat_control.a * tex2D (_Splat3, IN.uv_Splat3).rgb * tex2D (_Splat3, IN.uv_Splat3 * -0.125).rgb * 0.9;
	norm += splat_control.a * UnpackNormal(tex2D(_BumpMap3, float2(IN.uv_Control.x * (_TerrainX/_Tile3), IN.uv_Control.y * (_TerrainZ/_Tile3))));
	
	o.Albedo = col;
	o.Normal = norm;
	
}
ENDCG  
}

// Fallback to Diffuse
Fallback "Diffuse"
}

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

using UnityEngine;

using System.Collections;

[ExecuteInEditMode]

public class CustomTerrainScriptAtsV2 : MonoBehaviour {

	public Texture2D BumpTerrain;

	public float TileX;

	public float TileY;

	public Texture2D[] Bump; 

	public float[] Tile;

	public float terrainSizeX;

	public float terrainSizeZ;

	

	void Update () {

		//Terrain.activeTerrain.heightmapPixelError = 1;

	    //Terrain.activeTerrain.basemapDistance = 40000;

	    //Terrain.activeTerrain.detailObjectDistance = 4000;



		

		Terrain terrainComp = (Terrain)GetComponent(typeof(Terrain));

		Shader.SetGlobalTexture("_BumpTerrain" , BumpTerrain);

		Shader.SetGlobalFloat("_TileX", TileX);

		Shader.SetGlobalFloat("_TileY", TileY);

		for  (int i = 0; i < Bump.Length; i++){

			Shader.SetGlobalTexture("_BumpMap"+i.ToString(), Bump[i]);

			Shader.SetGlobalFloat("_Tile"+i.ToString(), Tile[i]);

			

		}

		/*

		if(Bump0)

			Shader.SetGlobalTexture("_BumpMap0", Bump0);

		

		if(Bump1)

			Shader.SetGlobalTexture("_BumpMap1", Bump1);

		

		if(Bump2)

			Shader.SetGlobalTexture("_BumpMap2", Bump2);

		

		if(Bump3)

			Shader.SetGlobalTexture("_BumpMap3", Bump3);

		

		Shader.SetGlobalFloat("_Tile0", Tile0);

		Shader.SetGlobalFloat("_Tile1", Tile1);

		Shader.SetGlobalFloat("_Tile2", Tile2);

		Shader.SetGlobalFloat("_Tile3", Tile3);

		*/

		terrainSizeX = terrainComp.terrainData.size.x;

		terrainSizeZ = terrainComp.terrainData.size.z;

		

		Shader.SetGlobalFloat("_TerrainX", terrainSizeX);

		Shader.SetGlobalFloat("_TerrainZ", terrainSizeZ);

	}



}

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 :smile:

c’on have u got any Idea? Here’s another link(go to terrain rendering)

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

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.

Terrains are my top 5 of complaints about Unity. I’d rather them starting over with a Voxel terrain than improving the current one.

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?

Yes.

Come on, any hint?

right now I’ve achieved this amazing result :

BTW I have a serious problem : It doesn’t look very well if seen near >.<’

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.

Demonstenes has a very harsh way of coming across sometimes… but in this particular case, i couldnt agree more.

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

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 :smile:

PS sorry but terrain textures aren’t so good, they look as if u have built the game with fastest graphical option

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.

Some pictures :



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

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

https://www.youtube.com/watch?v=xImY7A53NUQ

Voxelform 2.0 - Editor

https://www.youtube.com/watch?v=Mr5htrZEYlw