Browse Source

Added a terrain material that uses height and slope information to map textures instead of alphamap.

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@7530 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
ant..om 14 years ago
parent
commit
4fa5522c8e

+ 76 - 0
engine/src/terrain/Common/MatDefs/Terrain/HeightBasedTerrain.frag

@@ -0,0 +1,76 @@
+uniform vec3 m_region1;
+uniform vec3 m_region2;
+uniform vec3 m_region3;
+uniform vec3 m_region4;
+
+uniform sampler2D m_region1ColorMap;
+uniform sampler2D m_region2ColorMap;
+uniform sampler2D m_region3ColorMap;
+uniform sampler2D m_region4ColorMap;
+uniform sampler2D m_slopeColorMap;
+
+uniform float m_slopeTileFactor;
+uniform float m_terrainSize;
+
+varying vec3 normal;
+varying vec4 position;
+
+vec4 GenerateTerrainColor() {
+    float height = position.y;
+    vec4 p = position / m_terrainSize;
+   
+    vec3 blend = abs( normal );
+    blend = (blend -0.2) * 0.7;
+    blend = normalize(max(blend, 0.00001));      // Force weights to sum to 1.0 (very important!)
+    float b = (blend.x + blend.y + blend.z);
+    blend /= vec3(b, b, b);
+
+    vec4 terrainColor = vec4(0, 0, 0, 1.0);
+
+    float m_regionMin = 0.0;
+    float m_regionMax = 0.0;
+    float m_regionRange = 0.0;
+    float m_regionWeight = 0.0;
+    
+ 	vec4 slopeCol1 = texture2D(m_slopeColorMap, p.yz * m_slopeTileFactor);
+ 	vec4 slopeCol2 = texture2D(m_slopeColorMap, p.xy * m_slopeTileFactor);
+
+    // Terrain m_region 1.
+    m_regionMin = m_region1.x;
+    m_regionMax = m_region1.y;
+    m_regionRange = m_regionMax - m_regionMin;
+    m_regionWeight = (m_regionRange - abs(height - m_regionMax)) / m_regionRange;
+    m_regionWeight = max(0.0, m_regionWeight);
+  	terrainColor += m_regionWeight * texture2D(m_region1ColorMap, p.xz * m_region1.z);
+
+    // Terrain m_region 2.
+    m_regionMin = m_region2.x;
+    m_regionMax = m_region2.y;
+    m_regionRange = m_regionMax - m_regionMin;
+    m_regionWeight = (m_regionRange - abs(height - m_regionMax)) / m_regionRange;
+    m_regionWeight = max(0.0, m_regionWeight);
+    terrainColor += m_regionWeight * (texture2D(m_region2ColorMap, p.xz * m_region2.z));
+
+    // Terrain m_region 3.
+    m_regionMin = m_region3.x;
+    m_regionMax = m_region3.y;
+    m_regionRange = m_regionMax - m_regionMin;
+    m_regionWeight = (m_regionRange - abs(height - m_regionMax)) / m_regionRange;
+    m_regionWeight = max(0.0, m_regionWeight);
+	terrainColor += m_regionWeight * texture2D(m_region3ColorMap, p.xz * m_region3.z);
+
+    // Terrain m_region 4.
+    m_regionMin = m_region4.x;
+    m_regionMax = m_region4.y;
+    m_regionRange = m_regionMax - m_regionMin;
+    m_regionWeight = (m_regionRange - abs(height - m_regionMax)) / m_regionRange;
+    m_regionWeight = max(0.0, m_regionWeight);
+    terrainColor += m_regionWeight * texture2D(m_region4ColorMap, p.xz * m_region4.z);
+
+    return (blend.y * terrainColor + blend.x * slopeCol1 + blend.z * slopeCol2);
+}
+
+void main() {  
+	vec4 color = GenerateTerrainColor();
+    gl_FragColor = color;
+}

+ 41 - 0
engine/src/terrain/Common/MatDefs/Terrain/HeightBasedTerrain.j3md

@@ -0,0 +1,41 @@
+MaterialDef Terrain {
+
+        // Parameters to material:
+        // regionXColorMap: X = 1..4 the texture that should be appliad to state X
+        // regionX: a Vector3f containing the following information:
+        //      regionX.x: the start height of the region
+        //      regionX.y: the end height of the region
+        //      regionX.z: the texture scale for the region
+        //  it might not be the most elegant way for storing these 3 values, but it packs the data nicely :)
+        // slopeColorMap: the texture to be used for cliffs, and steep mountain sites
+        // slopeTileFactor: the texture scale for slopes
+        // terrainSize: the total size of the terrain (used for scaling the texture)
+	MaterialParameters {
+		Texture2D region1ColorMap
+		Texture2D region2ColorMap
+		Texture2D region3ColorMap
+		Texture2D region4ColorMap
+		Texture2D slopeColorMap
+		Float slopeTileFactor
+		Float terrainSize
+		Vector3 region1
+		Vector3 region2
+		Vector3 region3
+		Vector3 region4
+	}
+
+	Technique {
+		VertexShader GLSL130:   Common/MatDefs/Terrain/HeightBasedTerrain.vert
+		FragmentShader GLSL130: Common/MatDefs/Terrain/HeightBasedTerrain.frag
+
+		WorldParameters {
+			WorldViewProjectionMatrix
+			WorldMatrix
+			NormalMatrix
+		}
+	}
+
+	Technique FixedFunc {
+    }
+
+}

+ 22 - 0
engine/src/terrain/Common/MatDefs/Terrain/HeightBasedTerrain.vert

@@ -0,0 +1,22 @@
+uniform float m_tilingFactor;
+uniform mat4 g_WorldViewProjectionMatrix;
+uniform mat4 g_WorldMatrix;
+uniform mat3 g_NormalMatrix;
+
+uniform float m_terrainSize;
+
+attribute vec4 inTexCoord;
+attribute vec3 inNormal;
+attribute vec3 inPosition;
+
+varying vec3 normal;
+varying vec4 position;
+
+void main()
+{
+ 	normal = normalize(inNormal);
+ 	position = g_WorldMatrix * vec4(inPosition, 0.0);
+    gl_Position = g_WorldViewProjectionMatrix * vec4(inPosition, 1);
+}
+
+

BIN
engine/src/test-data/Textures/Terrain/grid/rock.jpg


+ 26 - 15
engine/src/test/jme3test/terrain/TerrainGridTest.java

@@ -60,29 +60,40 @@ public class TerrainGridTest extends SimpleApplication {
         this.stateManager.attach(state);
 
         // TERRAIN TEXTURE material
-        mat_terrain = new Material(assetManager, "Common/MatDefs/Terrain/Terrain.j3md");
-        mat_terrain.setBoolean("useTriPlanarMapping", false);
-
-        // ALPHA map (for splat textures)
-        mat_terrain.setTexture("Alpha", assetManager.loadTexture("Textures/Terrain/splat/alphamap.png"));
-
+        this.mat_terrain = new Material(this.assetManager, "Common/MatDefs/Terrain/HeightBasedTerrain.j3md");
+
+        // Parameters to material:
+        // regionXColorMap: X = 1..4 the texture that should be appliad to state X
+        // regionX: a Vector3f containing the following information:
+        //      regionX.x: the start height of the region
+        //      regionX.y: the end height of the region
+        //      regionX.z: the texture scale for the region
+        //  it might not be the most elegant way for storing these 3 values, but it packs the data nicely :)
+        // slopeColorMap: the texture to be used for cliffs, and steep mountain sites
+        // slopeTileFactor: the texture scale for slopes
+        // terrainSize: the total size of the terrain (used for scaling the texture)
         // GRASS texture
-        Texture grass = assetManager.loadTexture("Textures/Terrain/splat/grass.jpg");
+        Texture grass = this.assetManager.loadTexture("Textures/Terrain/splat/grass.jpg");
         grass.setWrap(WrapMode.Repeat);
-        mat_terrain.setTexture("Tex1", grass);
-        mat_terrain.setFloat("Tex1Scale", grassScale);
+        this.mat_terrain.setTexture("region1ColorMap", grass);
+        this.mat_terrain.setVector3("region1", new Vector3f(88, 200, this.grassScale));
 
         // DIRT texture
-        Texture dirt = assetManager.loadTexture("Textures/Terrain/splat/dirt.jpg");
+        Texture dirt = this.assetManager.loadTexture("Textures/Terrain/splat/dirt.jpg");
         dirt.setWrap(WrapMode.Repeat);
-        mat_terrain.setTexture("Tex2", dirt);
-        mat_terrain.setFloat("Tex2Scale", dirtScale);
+        this.mat_terrain.setTexture("region2ColorMap", dirt);
+        this.mat_terrain.setVector3("region2", new Vector3f(0, 90, this.dirtScale));
 
         // ROCK texture
-        Texture rock = assetManager.loadTexture("Textures/Terrain/splat/road.jpg");
+        Texture rock = this.assetManager.loadTexture("Textures/Terrain/grid/rock.jpg");
         rock.setWrap(WrapMode.Repeat);
-        mat_terrain.setTexture("Tex3", rock);
-        mat_terrain.setFloat("Tex3Scale", rockScale);
+        this.mat_terrain.setTexture("region3ColorMap", rock);
+        this.mat_terrain.setVector3("region3", new Vector3f(198, 260, this.rockScale));
+
+        this.mat_terrain.setTexture("slopeColorMap", rock);
+        this.mat_terrain.setFloat("slopeTileFactor", 32);
+
+        this.mat_terrain.setFloat("terrainSize", 513);
 
         this.base = new FractalSum();
         this.base.setRoughness(0.7f);