I’ve modified the terrain texture blending to allow nicer looking blending of the different texture layers.
The idea behind this is to treat the different layers you paint in the terrain editor as height not as alpha, this height value gets modified by the height map of the terrain textures(I’m currently using the diffuse textures alpha channel for this). The heighest value will then be drawn, with blending if textures are at similar heights.
Height based terrain splatting:
The algorithm to determine the visibility of a texture looks like this:
[java]
// global variable to compare heights of different alpha maps and textures.
float height = 0.0;
// defines strength of the alpha in comparison to the blending textures.
// calculate visibility of texture.
float calculateAlphaBlend(in float alphaMap, in float textureBlend){
// combined height of alphaMap and texture.
textureBlend += alphaMap * 2.0;
// a blending value to soften transition between textures
alphaMap = (clamp(textureBlend - height, -0.125,0.125)+0.125)*4.0;
if (textureBlend > height)
{
height = textureBlend;
}
return alphaMap;
}
[/java]
The parallax mapping part is just the already existing parallax mapping with a modified texture look up because it has to sample all texture layers.
I’ve added a few new parameters to the terrain material:
[java]
Boolean blendWithAlpha - this acitvates the new height based terrain splatting.
Boolean parallaxMapping - this activates parallax mapping.
Boolean steepParallax - switches between parallax mapping and steep parallax mapping
Float parallaxHeight - sets the strength of the parallax effect
Float parallaxSamples - is used to set the number of samples for steep parallax mapping
[/java]
Now the actual Code for the modified TerrainLighting.j3md and TerrainLighting.frag
TerrainLighting.j3md:
[java]
// NOTE: Doesn’t support OpenGL1
MaterialDef Terrain Lighting {
MaterialParameters {
// use tri-planar mapping
Boolean useTriPlanarMapping
// Use ward specular instead of phong
Boolean WardIso
// Are we rendering TerrainGrid
Boolean isTerrainGrid
// Use alpha channel of diffuse texture to blend with structure
Boolean blendWithAlpha
// Use alpha channel of diffuse texture for parallax mapping;
Boolean parallaxMapping
Boolean steepParallax
Float ParallaxHeight : 0.005
Float ParallaxSamples : 16
// Ambient color
Color Ambient
// Diffuse color
Color Diffuse
// Specular color
Color Specular
// Specular power/shininess
Float Shininess : 0
// Texture map #0
Texture2D DiffuseMap
Float DiffuseMap_0_scale
Texture2D NormalMap
// Texture map #1
Texture2D DiffuseMap_1
Float DiffuseMap_1_scale
Texture2D NormalMap_1
// Texture map #2
Texture2D DiffuseMap_2
Float DiffuseMap_2_scale
Texture2D NormalMap_2
// Texture map #3
Texture2D DiffuseMap_3
Float DiffuseMap_3_scale
Texture2D NormalMap_3
// Texture map #4
Texture2D DiffuseMap_4
Float DiffuseMap_4_scale
Texture2D NormalMap_4
// Texture map #5
Texture2D DiffuseMap_5
Float DiffuseMap_5_scale
Texture2D NormalMap_5
// Texture map #6
Texture2D DiffuseMap_6
Float DiffuseMap_6_scale
Texture2D NormalMap_6
// Texture map #7
Texture2D DiffuseMap_7
Float DiffuseMap_7_scale
Texture2D NormalMap_7
// Texture map #8
Texture2D DiffuseMap_8
Float DiffuseMap_8_scale
Texture2D NormalMap_8
// Texture map #9
Texture2D DiffuseMap_9
Float DiffuseMap_9_scale
Texture2D NormalMap_9
// Texture map #10
Texture2D DiffuseMap_10
Float DiffuseMap_10_scale
Texture2D NormalMap_10
// Texture map #11
Texture2D DiffuseMap_11
Float DiffuseMap_11_scale
Texture2D NormalMap_11
// Specular/gloss map
Texture2D SpecularMap
// Texture that specifies alpha values
Texture2D AlphaMap
Texture2D AlphaMap_1
Texture2D AlphaMap_2
// Texture of the glowing parts of the material
Texture2D GlowMap
// The glow color of the object
Color GlowColor
}
Technique {
LightMode MultiPass
VertexShader GLSL100: MatDefs/Terrain/TerrainLighting.vert
FragmentShader GLSL100: MatDefs/Terrain/TerrainLighting.frag
WorldParameters {
WorldViewProjectionMatrix
NormalMatrix
WorldViewMatrix
ViewMatrix
}
Defines {
TRI_PLANAR_MAPPING : useTriPlanarMapping
TERRAIN_GRID : isTerrainGrid
WARDISO : WardIso
BLENDWITHALPHA : blendWithAlpha
PARALLAXMAPPING : parallaxMapping
STEEPPARALLAX : steepParallax
DIFFUSEMAP : DiffuseMap
DIFFUSEMAP_1 : DiffuseMap_1
DIFFUSEMAP_2 : DiffuseMap_2
DIFFUSEMAP_3 : DiffuseMap_3
DIFFUSEMAP_4 : DiffuseMap_4
DIFFUSEMAP_5 : DiffuseMap_5
DIFFUSEMAP_6 : DiffuseMap_6
DIFFUSEMAP_7 : DiffuseMap_7
DIFFUSEMAP_8 : DiffuseMap_8
DIFFUSEMAP_9 : DiffuseMap_9
DIFFUSEMAP_10 : DiffuseMap_10
DIFFUSEMAP_11 : DiffuseMap_11
NORMALMAP : NormalMap
NORMALMAP_1 : NormalMap_1
NORMALMAP_2 : NormalMap_2
NORMALMAP_3 : NormalMap_3
NORMALMAP_4 : NormalMap_4
NORMALMAP_5 : NormalMap_5
NORMALMAP_6 : NormalMap_6
NORMALMAP_7 : NormalMap_7
NORMALMAP_8 : NormalMap_8
NORMALMAP_9 : NormalMap_9
NORMALMAP_10 : NormalMap_10
NORMALMAP_11 : NormalMap_11
SPECULARMAP : SpecularMap
ALPHAMAP : AlphaMap
ALPHAMAP_1 : AlphaMap_1
ALPHAMAP_2 : AlphaMap_2
DIFFUSEMAP_0_SCALE : DiffuseMap_0_scale
DIFFUSEMAP_1_SCALE : DiffuseMap_1_scale
DIFFUSEMAP_2_SCALE : DiffuseMap_2_scale
DIFFUSEMAP_3_SCALE : DiffuseMap_3_scale
DIFFUSEMAP_4_SCALE : DiffuseMap_4_scale
DIFFUSEMAP_5_SCALE : DiffuseMap_5_scale
DIFFUSEMAP_6_SCALE : DiffuseMap_6_scale
DIFFUSEMAP_7_SCALE : DiffuseMap_7_scale
DIFFUSEMAP_8_SCALE : DiffuseMap_8_scale
DIFFUSEMAP_9_SCALE : DiffuseMap_9_scale
DIFFUSEMAP_10_SCALE : DiffuseMap_10_scale
DIFFUSEMAP_11_SCALE : DiffuseMap_11_scale
}
}
Technique PreShadow {
VertexShader GLSL100 : Common/MatDefs/Shadow/PreShadow.vert
FragmentShader GLSL100 : Common/MatDefs/Shadow/PreShadow.frag
WorldParameters {
WorldViewProjectionMatrix
WorldViewMatrix
}
Defines {
DIFFUSEMAP_ALPHA : DiffuseMap
}
RenderState {
FaceCull Off
DepthTest On
DepthWrite On
PolyOffset 5 0
ColorWrite Off
}
}
Technique PreNormalPass {
VertexShader GLSL100 : Common/MatDefs/SSAO/normal.vert
FragmentShader GLSL100 : Common/MatDefs/SSAO/normal.frag
WorldParameters {
WorldViewProjectionMatrix
WorldViewMatrix
NormalMatrix
}
Defines {
DIFFUSEMAP_ALPHA : DiffuseMap
}
RenderState {
}
}
Technique GBuf {
VertexShader GLSL100: Common/MatDefs/Light/GBuf.vert
FragmentShader GLSL100: Common/MatDefs/Light/GBuf.frag
WorldParameters {
WorldViewProjectionMatrix
WorldMatrix
}
Defines {
VERTEX_COLOR : UseVertexColor
MATERIAL_COLORS : UseMaterialColors
V_TANGENT : VTangent
MINNAERT : Minnaert
WARDISO : WardIso
DIFFUSEMAP : DiffuseMap
NORMALMAP : NormalMap
SPECULARMAP : SpecularMap
PARALLAXMAP : ParallaxMap
}
}
Technique {
LightMode FixedPipeline
}
Technique Glow {
VertexShader GLSL100: Common/MatDefs/Misc/Unshaded.vert
FragmentShader GLSL100: Common/MatDefs/Light/Glow.frag
WorldParameters {
WorldViewProjectionMatrix
}
Defines {
HAS_GLOWMAP : GlowMap
HAS_GLOWCOLOR : GlowColor
}
}
}
[/java]
TerrainLighting.frag:
[java]
uniform float m_Shininess;
uniform vec4 g_LightDirection;
varying vec4 AmbientSum;
varying vec4 DiffuseSum;
varying vec4 SpecularSum;
varying vec3 vNormal;
varying vec2 texCoord;
varying vec3 vPosition;
varying vec3 vnPosition;
varying vec3 vViewDir;
varying vec4 vLightDir;
varying vec4 vnLightDir;
varying vec3 lightVec;
#ifdef PARALLAXMAPPING
uniform float m_ParallaxHeight;
#ifdef STEEPPARALLAX
uniform float m_ParallaxSamples;
#endif
#endif
#ifdef DIFFUSEMAP
uniform sampler2D m_DiffuseMap;
#endif
#ifdef DIFFUSEMAP_1
uniform sampler2D m_DiffuseMap_1;
#endif
#ifdef DIFFUSEMAP_2
uniform sampler2D m_DiffuseMap_2;
#endif
#ifdef DIFFUSEMAP_3
uniform sampler2D m_DiffuseMap_3;
#endif
#ifdef DIFFUSEMAP_4
uniform sampler2D m_DiffuseMap_4;
#endif
#ifdef DIFFUSEMAP_5
uniform sampler2D m_DiffuseMap_5;
#endif
#ifdef DIFFUSEMAP_6
uniform sampler2D m_DiffuseMap_6;
#endif
#ifdef DIFFUSEMAP_7
uniform sampler2D m_DiffuseMap_7;
#endif
#ifdef DIFFUSEMAP_8
uniform sampler2D m_DiffuseMap_8;
#endif
#ifdef DIFFUSEMAP_9
uniform sampler2D m_DiffuseMap_9;
#endif
#ifdef DIFFUSEMAP_10
uniform sampler2D m_DiffuseMap_10;
#endif
#ifdef DIFFUSEMAP_11
uniform sampler2D m_DiffuseMap_11;
#endif
#ifdef DIFFUSEMAP_0_SCALE
uniform float m_DiffuseMap_0_scale;
#endif
#ifdef DIFFUSEMAP_1_SCALE
uniform float m_DiffuseMap_1_scale;
#endif
#ifdef DIFFUSEMAP_2_SCALE
uniform float m_DiffuseMap_2_scale;
#endif
#ifdef DIFFUSEMAP_3_SCALE
uniform float m_DiffuseMap_3_scale;
#endif
#ifdef DIFFUSEMAP_4_SCALE
uniform float m_DiffuseMap_4_scale;
#endif
#ifdef DIFFUSEMAP_5_SCALE
uniform float m_DiffuseMap_5_scale;
#endif
#ifdef DIFFUSEMAP_6_SCALE
uniform float m_DiffuseMap_6_scale;
#endif
#ifdef DIFFUSEMAP_7_SCALE
uniform float m_DiffuseMap_7_scale;
#endif
#ifdef DIFFUSEMAP_8_SCALE
uniform float m_DiffuseMap_8_scale;
#endif
#ifdef DIFFUSEMAP_9_SCALE
uniform float m_DiffuseMap_9_scale;
#endif
#ifdef DIFFUSEMAP_10_SCALE
uniform float m_DiffuseMap_10_scale;
#endif
#ifdef DIFFUSEMAP_11_SCALE
uniform float m_DiffuseMap_11_scale;
#endif
#ifdef ALPHAMAP
uniform sampler2D m_AlphaMap;
#endif
#ifdef ALPHAMAP_1
uniform sampler2D m_AlphaMap_1;
#endif
#ifdef ALPHAMAP_2
uniform sampler2D m_AlphaMap_2;
#endif
#ifdef NORMALMAP
uniform sampler2D m_NormalMap;
#endif
#ifdef NORMALMAP_1
uniform sampler2D m_NormalMap_1;
#endif
#ifdef NORMALMAP_2
uniform sampler2D m_NormalMap_2;
#endif
#ifdef NORMALMAP_3
uniform sampler2D m_NormalMap_3;
#endif
#ifdef NORMALMAP_4
uniform sampler2D m_NormalMap_4;
#endif
#ifdef NORMALMAP_5
uniform sampler2D m_NormalMap_5;
#endif
#ifdef NORMALMAP_6
uniform sampler2D m_NormalMap_6;
#endif
#ifdef NORMALMAP_7
uniform sampler2D m_NormalMap_7;
#endif
#ifdef NORMALMAP_8
uniform sampler2D m_NormalMap_8;
#endif
#ifdef NORMALMAP_9
uniform sampler2D m_NormalMap_9;
#endif
#ifdef NORMALMAP_10
uniform sampler2D m_NormalMap_10;
#endif
#ifdef NORMALMAP_11
uniform sampler2D m_NormalMap_11;
#endif
#ifdef TRI_PLANAR_MAPPING
varying vec4 wVertex;
varying vec3 wNormal;
#endif
float tangDot(in vec3 v1, in vec3 v2){
float d = dot(v1,v2);
#ifdef V_TANGENT
d = 1.0 - d*d;
return step(0.0, d) * sqrt(d);
#else
return d;
#endif
}
float lightComputeDiffuse(in vec3 norm, in vec3 lightdir, in vec3 viewdir){
return max(0.0, dot(norm, lightdir));
}
float lightComputeSpecular(in vec3 norm, in vec3 viewdir, in vec3 lightdir, in float shiny){
#ifdef WARDISO
// Isotropic Ward
vec3 halfVec = normalize(viewdir + lightdir);
float NdotH = max(0.001, tangDot(norm, halfVec));
float NdotV = max(0.001, tangDot(norm, viewdir));
float NdotL = max(0.001, tangDot(norm, lightdir));
float a = tan(acos(NdotH));
float p = max(shiny/128.0, 0.001);
return NdotL * (1.0 / (4.03.14159265pp)) * (exp(-(aa)/(p*p)) / (sqrt(NdotV * NdotL)));
#else
// Standard Phong
vec3 R = reflect(-lightdir, norm);
return pow(max(tangDot(R, viewdir), 0.0), shiny);
#endif
}
vec2 computeLighting(in vec3 wvPos, in vec3 wvNorm, in vec3 wvViewDir, in vec3 wvLightDir){
float diffuseFactor = lightComputeDiffuse(wvNorm, wvLightDir, wvViewDir);
float specularFactor = lightComputeSpecular(wvNorm, wvViewDir, wvLightDir, m_Shininess);
if (m_Shininess <= 1.0) {
specularFactor = 0.0; // should be one instruction on most cards …
}
float att = vLightDir.w;
return vec2(diffuseFactor, specularFactor) * vec2(att);
}
#ifdef BLENDWITHALPHA
// global variable to compare heights of different alpha maps and textures.
float height = 0.0;
// defines strength of the alpha in comparison to the blending textures.
// calculate visibility of texture.
float calculateAlphaBlend(in float alphaMap, in float textureBlend){
// combined height of alphaMap and texture.
textureBlend += alphaMap * 2.0;
// a blending value to soften transition between textures
alphaMap = (clamp(textureBlend - height, -0.125,0.125)+0.125)*4.0;
if (textureBlend > height)
{
height = textureBlend;
}
return alphaMap;
}
#endif
#ifdef ALPHAMAP
vec4 calculateDiffuseBlend(in vec2 texCoord) {
vec4 alphaBlend = texture2D( m_AlphaMap, texCoord.xy );
#ifdef ALPHAMAP_1
vec4 alphaBlend1 = texture2D( m_AlphaMap_1, texCoord.xy );
#endif
#ifdef ALPHAMAP_2
vec4 alphaBlend2 = texture2D( m_AlphaMap_2, texCoord.xy );
#endif
vec4 diffuseColor = texture2D(m_DiffuseMap, texCoord * m_DiffuseMap_0_scale);
#ifdef BLENDWITHALPHA
height = 0.0;
alphaBlend.r = calculateAlphaBlend(alphaBlend.r, diffuseColor.a);
#endif
diffuseColor *= alphaBlend.r;
#ifdef DIFFUSEMAP_1
vec4 diffuseColor1 = texture2D(m_DiffuseMap_1, texCoord * m_DiffuseMap_1_scale);
#ifdef BLENDWITHALPHA
alphaBlend.g = calculateAlphaBlend(alphaBlend.g, diffuseColor1.a);
#endif
diffuseColor = mix( diffuseColor, diffuseColor1, alphaBlend.g);
#ifdef DIFFUSEMAP_2
vec4 diffuseColor2 = texture2D(m_DiffuseMap_2, texCoord * m_DiffuseMap_2_scale);
#ifdef BLENDWITHALPHA
alphaBlend.b = calculateAlphaBlend(alphaBlend.b, diffuseColor2.a);
#endif
diffuseColor = mix( diffuseColor, diffuseColor2, alphaBlend.b );
#ifdef DIFFUSEMAP_3
vec4 diffuseColor3 = texture2D(m_DiffuseMap_3, texCoord * m_DiffuseMap_3_scale);
#ifdef BLENDWITHALPHA
alphaBlend.a = calculateAlphaBlend(alphaBlend.a, diffuseColor3.a);
#endif
diffuseColor = mix( diffuseColor, diffuseColor3, alphaBlend.a );
#ifdef ALPHAMAP_1
#ifdef DIFFUSEMAP_4
vec4 diffuseColor4 = texture2D(m_DiffuseMap_4, texCoord * m_DiffuseMap_4_scale);
#ifdef BLENDWITHALPHA
alphaBlend1.r = calculateAlphaBlend(alphaBlend1.r, diffuseColor4.a);
#endif
diffuseColor = mix( diffuseColor, diffuseColor4, alphaBlend1.r );
#ifdef DIFFUSEMAP_5
vec4 diffuseColor5 = texture2D(m_DiffuseMap_5, texCoord * m_DiffuseMap_5_scale);
#ifdef BLENDWITHALPHA
alphaBlend1.g = calculateAlphaBlend(alphaBlend1.g, diffuseColor5.a);
#endif
diffuseColor = mix( diffuseColor, diffuseColor5, alphaBlend1.g );
#ifdef DIFFUSEMAP_6
vec4 diffuseColor6 = texture2D(m_DiffuseMap_6, texCoord * m_DiffuseMap_6_scale);
#ifdef BLENDWITHALPHA
alphaBlend1.b = calculateAlphaBlend(alphaBlend1.b, diffuseColor6.a);
#endif
diffuseColor = mix( diffuseColor, diffuseColor6, alphaBlend1.b );
#ifdef DIFFUSEMAP_7
vec4 diffuseColor7 = texture2D(m_DiffuseMap_7, texCoord * m_DiffuseMap_7_scale);
#ifdef BLENDWITHALPHA
alphaBlend1.a = calculateAlphaBlend(alphaBlend1.a, diffuseColor7.a);
#endif
diffuseColor = mix( diffuseColor, diffuseColor7, alphaBlend1.a );
#ifdef ALPHAMAP_2
#ifdef DIFFUSEMAP_8
vec4 diffuseColor8 = texture2D(m_DiffuseMap_8, texCoord * m_DiffuseMap_8_scale);
#ifdef BLENDWITHALPHA
alphaBlend2.r = calculateAlphaBlend(alphaBlend2.r, diffuseColor8.a);
#endif
diffuseColor = mix( diffuseColor, diffuseColor8, alphaBlend2.r );
#ifdef DIFFUSEMAP_9
vec4 diffuseColor9 = texture2D(m_DiffuseMap_9, texCoord * m_DiffuseMap_9_scale);
#ifdef BLENDWITHALPHA
alphaBlend2.g = calculateAlphaBlend(alphaBlend2.g, diffuseColor9.a);
#endif
diffuseColor = mix( diffuseColor, diffuseColor9, alphaBlend2.g );
#ifdef DIFFUSEMAP_10
vec4 diffuseColor10 = texture2D(m_DiffuseMap_10, texCoord * m_DiffuseMap_10_scale);
#ifdef BLENDWITHALPHA
alphaBlend2.b = calculateAlphaBlend(alphaBlend2.b, diffuseColor10.a);
#endif
diffuseColor = mix( diffuseColor, diffuseColor10, alphaBlend2.b );
#ifdef DIFFUSEMAP_11
vec4 diffuseColor11 = texture2D(m_DiffuseMap_11, texCoord * m_DiffuseMap_11_scale);
#ifdef BLENDWITHALPHA
alphaBlend2.a = calculateAlphaBlend(alphaBlend2.a, diffuseColor11.a);
#endif
diffuseColor = mix( diffuseColor, diffuseColor11, alphaBlend2.a );
#endif
#endif
#endif
#endif
#endif
#endif
#endif
#endif
#endif
#endif
#endif
#endif
#endif
return diffuseColor;
}
vec3 calculateNormal(in vec2 texCoord) {
vec3 normal = vec3(0.5,0.5,1.0);
vec3 n = vec3(0.0,0.0,0.0);
vec4 alphaBlend = texture2D( m_AlphaMap, texCoord.xy );
#ifdef ALPHAMAP_1
vec4 alphaBlend1 = texture2D( m_AlphaMap_1, texCoord.xy );
#endif
#ifdef ALPHAMAP_2
vec4 alphaBlend2 = texture2D( m_AlphaMap_2, texCoord.xy );
#endif
#ifdef BLENDWITHALPHA
height = 0.0;
alphaBlend.r = calculateAlphaBlend(alphaBlend.r, texture2D(m_DiffuseMap, texCoord * m_DiffuseMap_0_scale).a);
#endif
#ifdef NORMALMAP
n = texture2D(m_NormalMap, texCoord * m_DiffuseMap_0_scale).xyz;
normal = mix (normal, n, alphaBlend.r);
#endif
#if defined(DIFFUSEMAP_1)&& defined(BLENDWITHALPHA)
alphaBlend.g = calculateAlphaBlend(alphaBlend.g, texture2D(m_DiffuseMap_1, texCoord * m_DiffuseMap_1_scale).a);
#endif
#ifdef NORMALMAP_1
n = texture2D(m_NormalMap_1, texCoord * m_DiffuseMap_1_scale).xyz;
normal = mix (normal, n, alphaBlend.g);
#else
#if defined(DIFFUSEMAP_1)
normal = mix (normal, vec3(0.5,0.5,1.0), alphaBlend.g);
#endif
#endif
#if defined(DIFFUSEMAP_2)&& defined(BLENDWITHALPHA)
alphaBlend.b = calculateAlphaBlend(alphaBlend.b, texture2D(m_DiffuseMap_2, texCoord * m_DiffuseMap_2_scale).a);
#endif
#ifdef NORMALMAP_2
n = texture2D(m_NormalMap_2, texCoord * m_DiffuseMap_2_scale).xyz;
normal = mix (normal, n, alphaBlend.b);
#else
#if defined(DIFFUSEMAP_2)
normal = mix (normal, vec3(0.5,0.5,1.0), alphaBlend.b);
#endif
#endif
#if defined(DIFFUSEMAP_3)&& defined(BLENDWITHALPHA)
alphaBlend.a = calculateAlphaBlend(alphaBlend.a, texture2D(m_DiffuseMap_3, texCoord * m_DiffuseMap_3_scale).a);
#endif
#ifdef NORMALMAP_3
n = texture2D(m_NormalMap_3, texCoord * m_DiffuseMap_3_scale).xyz;
normal = mix (normal, n, alphaBlend.a);
#else
#if defined(DIFFUSEMAP_3)
normal = mix (normal, vec3(0.5,0.5,1.0), alphaBlend.a);
#endif
#endif
#ifdef ALPHAMAP_1
#if defined(DIFFUSEMAP_4)&& defined(BLENDWITHALPHA)
alphaBlend1.r = calculateAlphaBlend(alphaBlend1.r, texture2D(m_DiffuseMap_4, texCoord * m_DiffuseMap_4_scale).a);
#endif
#ifdef NORMALMAP_4
n = texture2D(m_NormalMap_4, texCoord * m_DiffuseMap_4_scale).xyz;
normal = mix (normal, n, alphaBlend1.r);
#else
#if defined(DIFFUSEMAP_4)
normal = mix (normal, vec3(0.5,0.5,1.0), alphaBlend1.r);
#endif
#endif
#if defined(DIFFUSEMAP_5)&& defined(BLENDWITHALPHA)
alphaBlend1.g = calculateAlphaBlend(alphaBlend1.g, texture2D(m_DiffuseMap_5, texCoord * m_DiffuseMap_5_scale).a);
#endif
#ifdef NORMALMAP_5
n = texture2D(m_NormalMap_5, texCoord * m_DiffuseMap_5_scale).xyz;
normal = mix (normal, n, alphaBlend1.g);
#else
#if defined(DIFFUSEMAP_5)
normal = mix (normal, vec3(0.5,0.5,1.0), alphaBlend1.g);
#endif
#endif
#if defined(DIFFUSEMAP_6)&& defined(BLENDWITHALPHA)
alphaBlend1.b = calculateAlphaBlend(alphaBlend1.b, texture2D(m_DiffuseMap_6, texCoord * m_DiffuseMap_6_scale).a);
#endif
#ifdef NORMALMAP_6
n = texture2D(m_NormalMap_6, texCoord * m_DiffuseMap_6_scale).xyz;
normal = mix (normal, n, alphaBlend1.b);
#else
#if defined(DIFFUSEMAP_6)
normal = mix (normal, vec3(0.5,0.5,1.0), alphaBlend1.b);
#endif
#endif
#if defined(DIFFUSEMAP_7)&& defined(BLENDWITHALPHA)
alphaBlend1.a = calculateAlphaBlend(alphaBlend1.a, texture2D(m_DiffuseMap_7, texCoord * m_DiffuseMap_7_scale).a);
#endif
#ifdef NORMALMAP_7
n = texture2D(m_NormalMap_7, texCoord * m_DiffuseMap_7_scale).xyz;
normal = mix (normal, n, alphaBlend1.a);
#else
#if defined(DIFFUSEMAP_7)
normal = mix (normal, vec3(0.5,0.5,1.0), alphaBlend1.a);
#endif
#endif
#endif
#ifdef ALPHAMAP_2
#if defined(DIFFUSEMAP_8)&& defined(BLENDWITHALPHA)
alphaBlend2.r = calculateAlphaBlend(alphaBlend2.r, texture2D(m_DiffuseMap_8, texCoord * m_DiffuseMap_8_scale).a);
#endif
#ifdef NORMALMAP_8
n = texture2D(m_NormalMap_8, texCoord * m_DiffuseMap_8_scale).xyz;
normal = mix (normal, n, alphaBlend2.r);
#else
#if defined(DIFFUSEMAP_8)
normal = mix (normal, vec3(0.5,0.5,1.0), alphaBlend2.r);
#endif
#endif
#if defined(DIFFUSEMAP_9)&& defined(BLENDWITHALPHA)
alphaBlend2.g = calculateAlphaBlend(alphaBlend2.g, texture2D(m_DiffuseMap_9, texCoord * m_DiffuseMap_9_scale).a);
#endif
#ifdef NORMALMAP_9
n = texture2D(m_NormalMap_9, texCoord * m_DiffuseMap_9_scale);
normal = mix (normal, n, alphaBlend2.g);
#else
#if defined(DIFFUSEMAP_9)
normal = mix (normal, vec3(0.5,0.5,1.0), alphaBlend2.g);
#endif
#endif
#if defined(DIFFUSEMAP_10)&& defined(BLENDWITHALPHA)
alphaBlend2.b = calculateAlphaBlend(alphaBlend2.b, texture2D(m_DiffuseMap_10, texCoord * m_DiffuseMap_10_scale).a);
#endif
#ifdef NORMALMAP_10
n = texture2D(m_NormalMap_10, texCoord * m_DiffuseMap_10_scale);
normal = mix (normal, n, alphaBlend2.b);
#else
#if defined(DIFFUSEMAP_10)
normal = mix (normal, vec3(0.5,0.5,1.0), alphaBlend2.b);
#endif
#endif
#if defined(DIFFUSEMAP_11)&& defined(BLENDWITHALPHA)
alphaBlend2.a = calculateAlphaBlend(alphaBlend2.a, texture2D(m_DiffuseMap_11, texCoord * m_DiffuseMap_11_scale).a);
#endif
#ifdef NORMALMAP_11
n = texture2D(m_NormalMap_11, texCoord * m_DiffuseMap_11_scale);
normal = mix (normal, n, alphaBlend2.a);
#else
#if defined(DIFFUSEMAP_11)
normal = mix (normal, vec3(0.5,0.5,1.0), alphaBlend2.a);
#endif
#endif
#endif
return normalize(normal.xyz * vec3(2.0) - vec3(1.0));
}
#ifdef TRI_PLANAR_MAPPING
vec4 getTriPlanarBlend(in vec4 coords, in vec3 blending, in sampler2D map, in float scale) {
vec4 col1 = texture2D( map, coords.yz * scale);
vec4 col2 = texture2D( map, coords.xz * scale);
vec4 col3 = texture2D( map, coords.xy * scale);
// blend the results of the 3 planar projections.
vec4 tex = col1 * blending.x + col2 * blending.y + col3 * blending.z;
return tex;
}
vec4 calculateTriPlanarDiffuseBlend(in vec3 wNorm, in vec4 wVert, in vec2 texCoord) {
// tri-planar texture bending factor for this fragment's normal
vec3 blending = abs( wNorm );
blending = (blending -0.2) * 0.7;
blending = normalize(max(blending, 0.00001)); // Force weights to sum to 1.0 (very important!)
float b = (blending.x + blending.y + blending.z);
blending /= vec3(b, b, b);
// texture coords
vec4 coords = wVert;
// blend the results of the 3 planar projections.
vec4 tex0 = getTriPlanarBlend(coords, blending, m_DiffuseMap, m_DiffuseMap_0_scale);
#ifdef DIFFUSEMAP_1
// blend the results of the 3 planar projections.
vec4 tex1 = getTriPlanarBlend(coords, blending, m_DiffuseMap_1, m_DiffuseMap_1_scale);
#endif
#ifdef DIFFUSEMAP_2
// blend the results of the 3 planar projections.
vec4 tex2 = getTriPlanarBlend(coords, blending, m_DiffuseMap_2, m_DiffuseMap_2_scale);
#endif
#ifdef DIFFUSEMAP_3
// blend the results of the 3 planar projections.
vec4 tex3 = getTriPlanarBlend(coords, blending, m_DiffuseMap_3, m_DiffuseMap_3_scale);
#endif
#ifdef DIFFUSEMAP_4
// blend the results of the 3 planar projections.
vec4 tex4 = getTriPlanarBlend(coords, blending, m_DiffuseMap_4, m_DiffuseMap_4_scale);
#endif
#ifdef DIFFUSEMAP_5
// blend the results of the 3 planar projections.
vec4 tex5 = getTriPlanarBlend(coords, blending, m_DiffuseMap_5, m_DiffuseMap_5_scale);
#endif
#ifdef DIFFUSEMAP_6
// blend the results of the 3 planar projections.
vec4 tex6 = getTriPlanarBlend(coords, blending, m_DiffuseMap_6, m_DiffuseMap_6_scale);
#endif
#ifdef DIFFUSEMAP_7
// blend the results of the 3 planar projections.
vec4 tex7 = getTriPlanarBlend(coords, blending, m_DiffuseMap_7, m_DiffuseMap_7_scale);
#endif
#ifdef DIFFUSEMAP_8
// blend the results of the 3 planar projections.
vec4 tex8 = getTriPlanarBlend(coords, blending, m_DiffuseMap_8, m_DiffuseMap_8_scale);
#endif
#ifdef DIFFUSEMAP_9
// blend the results of the 3 planar projections.
vec4 tex9 = getTriPlanarBlend(coords, blending, m_DiffuseMap_9, m_DiffuseMap_9_scale);
#endif
#ifdef DIFFUSEMAP_10
// blend the results of the 3 planar projections.
vec4 tex10 = getTriPlanarBlend(coords, blending, m_DiffuseMap_10, m_DiffuseMap_10_scale);
#endif
#ifdef DIFFUSEMAP_11
// blend the results of the 3 planar projections.
vec4 tex11 = getTriPlanarBlend(coords, blending, m_DiffuseMap_11, m_DiffuseMap_11_scale);
#endif
vec4 alphaBlend = texture2D( m_AlphaMap, texCoord.xy );
#ifdef ALPHAMAP_1
vec4 alphaBlend1 = texture2D( m_AlphaMap_1, texCoord.xy );
#endif
#ifdef ALPHAMAP_2
vec4 alphaBlend2 = texture2D( m_AlphaMap_2, texCoord.xy );
#endif
#ifdef BLENDWITHALPHA
alphaBlend.r = calculateAlphaBlend(alphaBlend.r, tex0.a);
#endif
vec4 diffuseColor = tex0 * alphaBlend.r;
#ifdef DIFFUSEMAP_1
#ifdef BLENDWITHALPHA
alphaBlend.g = calculateAlphaBlend(alphaBlend.g, tex1.a);
#endif
diffuseColor = mix( diffuseColor, tex1, alphaBlend.g );
#ifdef DIFFUSEMAP_2
#ifdef BLENDWITHALPHA
alphaBlend.b = calculateAlphaBlend(alphaBlend.b, tex2.a);
#endif
diffuseColor = mix( diffuseColor, tex2, alphaBlend.b );
#ifdef DIFFUSEMAP_3
#ifdef BLENDWITHALPHA
alphaBlend.a = calculateAlphaBlend(alphaBlend.a, tex3.a);
#endif
diffuseColor = mix( diffuseColor, tex3, alphaBlend.a );
#ifdef ALPHAMAP_1
#ifdef DIFFUSEMAP_4
#ifdef BLENDWITHALPHA
alphaBlend1.r = calculateAlphaBlend(alphaBlend1.r, tex4.a);
#endif
diffuseColor = mix( diffuseColor, tex4, alphaBlend1.r );
#ifdef DIFFUSEMAP_5
#ifdef BLENDWITHALPHA
alphaBlend1.g = calculateAlphaBlend(alphaBlend1.g, tex5.a);
#endif
diffuseColor = mix( diffuseColor, tex5, alphaBlend1.g );
#ifdef DIFFUSEMAP_6
#ifdef BLENDWITHALPHA
alphaBlend1.b = calculateAlphaBlend(alphaBlend1.b, tex6.a);
#endif
diffuseColor = mix( diffuseColor, tex6, alphaBlend1.b );
#ifdef DIFFUSEMAP_7
#ifdef BLENDWITHALPHA
alphaBlend1.a = calculateAlphaBlend(alphaBlend1.a, tex7.a);
#endif
diffuseColor = mix( diffuseColor, tex7, alphaBlend1.a );
#ifdef ALPHAMAP_2
#ifdef DIFFUSEMAP_8
#ifdef BLENDWITHALPHA
alphaBlend2.r = calculateAlphaBlend(alphaBlend2.r, tex8.a);
#endif
diffuseColor = mix( diffuseColor, tex8, alphaBlend2.r );
#ifdef DIFFUSEMAP_9
#ifdef BLENDWITHALPHA
alphaBlend2.g = calculateAlphaBlend(alphaBlend2.g, tex9.a);
#endif
diffuseColor = mix( diffuseColor, tex9, alphaBlend2.g );
#ifdef DIFFUSEMAP_10
#ifdef BLENDWITHALPHA
alphaBlend2.b = calculateAlphaBlend(alphaBlend2.b, tex10.a);
#endif
diffuseColor = mix( diffuseColor, tex10, alphaBlend2.b );
#ifdef DIFFUSEMAP_11
#ifdef BLENDWITHALPHA
alphaBlend2.a = calculateAlphaBlend(alphaBlend2.a, tex11.a);
#endif
diffuseColor = mix( diffuseColor, tex11, alphaBlend2.a );
#endif
#endif
#endif
#endif
#endif
#endif
#endif
#endif
#endif
#endif
#endif
#endif
#endif
return diffuseColor;
}
vec3 calculateNormalTriPlanar(in vec3 wNorm, in vec4 wVert,in vec2 texCoord) {
// tri-planar texture bending factor for this fragment's world-space normal
vec3 blending = abs( wNorm );
blending = (blending -0.2) * 0.7;
blending = normalize(max(blending, 0.00001)); // Force weights to sum to 1.0 (very important!)
float b = (blending.x + blending.y + blending.z);
blending /= vec3(b, b, b);
// texture coords
vec4 coords = wVert;
vec4 alphaBlend = texture2D( m_AlphaMap, texCoord.xy );
#ifdef ALPHAMAP_1
vec4 alphaBlend1 = texture2D( m_AlphaMap_1, texCoord.xy );
#endif
#ifdef ALPHAMAP_2
vec4 alphaBlend2 = texture2D( m_AlphaMap_2, texCoord.xy );
#endif
vec3 normal = vec3(0.5,0.5,1.0);
vec3 n = vec3(0,0,0);
#if defined(DIFFUSEMAP)&& defined(BLENDWITHALPHA)
alphaBlend.r = calculateAlphaBlend(alphaBlend.r, getTriPlanarBlend(coords, blending, m_DiffuseMap, m_DiffuseMap_0_scale).a);
#endif
#ifdef NORMALMAP
n = getTriPlanarBlend(coords, blending, m_NormalMap, m_DiffuseMap_0_scale).xyz;
normal = mix(normal, n, alphaBlend.r);
#endif
#if defined(DIFFUSEMAP_1)&& defined(BLENDWITHALPHA)
alphaBlend.g = calculateAlphaBlend(alphaBlend.g, getTriPlanarBlend(coords, blending, m_DiffuseMap_1, m_DiffuseMap_1_scale).a);
#endif
#ifdef NORMALMAP_1
n = getTriPlanarBlend(coords, blending, m_NormalMap_1, m_DiffuseMap_1_scale).xyz;
normal = mix(normal, n, alphaBlend.g);
#else
normal = mix(normal, vec3(0.5,0.5,1.0), alphaBlend.g);
#endif
#if defined(DIFFUSEMAP_2)&& defined(BLENDWITHALPHA)
alphaBlend.b = calculateAlphaBlend(alphaBlend.b, getTriPlanarBlend(coords, blending, m_DiffuseMap_2, m_DiffuseMap_2_scale).a);
#endif
#ifdef NORMALMAP_2
n = getTriPlanarBlend(coords, blending, m_NormalMap_2, m_DiffuseMap_2_scale).xyz;
normal = mix(normal, n, alphaBlend.b);
#else
normal = mix(normal, vec3(0.5,0.5,1.0), alphaBlend.b);
#endif
#if defined(DIFFUSEMAP_3)&& defined(BLENDWITHALPHA)
alphaBlend.a = calculateAlphaBlend(alphaBlend.a, getTriPlanarBlend(coords, blending, m_DiffuseMap_3, m_DiffuseMap_3_scale).a);
#endif
#ifdef NORMALMAP_3
n = getTriPlanarBlend(coords, blending, m_NormalMap_3, m_DiffuseMap_3_scale).xyz;
normal = mix(normal, n, alphaBlend.a);
#else
normal = mix(normal, vec3(0.5,0.5,1.0), alphaBlend.a);
#endif
#ifdef ALPHAMAP_1
#if defined(DIFFUSEMAP_4)&& defined(BLENDWITHALPHA)
alphaBlend1.r = calculateAlphaBlend(alphaBlend1.r, getTriPlanarBlend(coords, blending, m_DiffuseMap_4, m_DiffuseMap_4_scale).a);
#endif
#ifdef NORMALMAP_4
n = getTriPlanarBlend(coords, blending, m_NormalMap_4, m_DiffuseMap_4_scale).xyz;
normal = mix(normal, n, alphaBlend1.r);
#else
normal = mix(normal, vec3(0.5,0.5,1.0), alphaBlend1.r);
#endif
#if defined(DIFFUSEMAP_5)&& defined(BLENDWITHALPHA)
alphaBlend1.g = calculateAlphaBlend(alphaBlend1.g, getTriPlanarBlend(coords, blending, m_DiffuseMap_5, m_DiffuseMap_5_scale).a);
#endif
#ifdef NORMALMAP_5
n = getTriPlanarBlend(coords, blending, m_NormalMap_5, m_DiffuseMap_5_scale).xyz;
normal = mix(normal, n, alphaBlend1.g);
#else
normal = mix(normal, vec3(0.5,0.5,1.0), alphaBlend1.g);
#endif
#if defined(DIFFUSEMAP_6)&& defined(BLENDWITHALPHA)
alphaBlend1.b = calculateAlphaBlend(alphaBlend1.b, getTriPlanarBlend(coords, blending, m_DiffuseMap_6, m_DiffuseMap_6_scale).a);
#endif
#ifdef NORMALMAP_6
n = getTriPlanarBlend(coords, blending, m_NormalMap_6, m_DiffuseMap_6_scale).xyz;
normal = mix(normal, n, alphaBlend1.b);
#else
normal = mix(normal, vec3(0.5,0.5,1.0), alphaBlend1.b);
#endif
#if defined(DIFFUSEMAP_7)&& defined(BLENDWITHALPHA)
alphaBlend1.a = calculateAlphaBlend(alphaBlend1.a, getTriPlanarBlend(coords, blending, m_DiffuseMap_7, m_DiffuseMap_7_scale).a);
#endif
#ifdef NORMALMAP_7
n = getTriPlanarBlend(coords, blending, m_NormalMap_7, m_DiffuseMap_7_scale).xyz;
normal = mix(normal, n, alphaBlend1.a);
#else
normal = mix(normal, vec3(0.5,0.5,1.0), alphaBlend1.a);
#endif
#endif
#ifdef ALPHAMAP_2
#if defined(DIFFUSEMAP_8)&& defined(BLENDWITHALPHA)
alphaBlend2.r = calculateAlphaBlend(alphaBlend2.r, getTriPlanarBlend(coords, blending, m_DiffuseMap_8, m_DiffuseMap_8_scale).a);
#endif
#ifdef NORMALMAP_8
n = getTriPlanarBlend(coords, blending, m_NormalMap_8, m_DiffuseMap_8_scale).xyz;
normal = mix(normal, n, alphaBlend2.r);
#else
normal = mix(normal, vec3(0.5,0.5,1.0), alphaBlend2.r);
#endif
#if defined(DIFFUSEMAP_9)&& defined(BLENDWITHALPHA)
alphaBlend2.g = calculateAlphaBlend(alphaBlend2.g, getTriPlanarBlend(coords, blending, m_DiffuseMap_9, m_DiffuseMap_9_scale).a);
#endif
#ifdef NORMALMAP_9
n = getTriPlanarBlend(coords, blending, m_NormalMap_9, m_DiffuseMap_9_scale).xyz;
normal = mix(normal, n, alphaBlend2.g);
#else
normal = mix(normal, vec3(0.5,0.5,1.0), alphaBlend2.g);
#endif
#if defined(DIFFUSEMAP_10)&& defined(BLENDWITHALPHA)
alphaBlend2.b = calculateAlphaBlend(alphaBlend2.b, getTriPlanarBlend(coords, blending, m_DiffuseMap_10, m_DiffuseMap_10_scale).a);
#endif
#ifdef NORMALMAP_10
n = getTriPlanarBlend(coords, blending, m_NormalMap_10, m_DiffuseMap_10_scale).xyz;
normal = mix(normal, n, alphaBlend2.b);
#else
normal = mix(normal, vec3(0.5,0.5,1.0), alphaBlend2.b);
#endif
#if defined(DIFFUSEMAP_11)&& defined(BLENDWITHALPHA)
alphaBlend2.a = calculateAlphaBlend(alphaBlend2.a, getTriPlanarBlend(coords, blending, m_DiffuseMap_11, m_DiffuseMap_11_scale).a);
#endif
#ifdef NORMALMAP_11
n = getTriPlanarBlend(coords, blending, m_NormalMap_11, m_DiffuseMap_11_scale).xyz;
normal = mix(normal, n, alphaBlend2.a);
#else
normal = mix(normal, vec3(0.5,0.5,1.0), alphaBlend2.a);
#endif
#endif
return normalize(normal.xyz * vec3(2.0) - vec3(1.0));
}
#endif
#endif
#if defined(PARALLAXMAPPING)&& defined(BLENDWITHALPHA)
float sampleHeight(in vec2 texCoord){
vec4 alphaBlend = texture2D( m_AlphaMap, texCoord.xy );
#ifdef ALPHAMAP_1
vec4 alphaBlend1 = texture2D( m_AlphaMap_1, texCoord.xy );
#endif
#ifdef ALPHAMAP_2
vec4 alphaBlend2 = texture2D( m_AlphaMap_2, texCoord.xy );
#endif
height = 0.0;
float alphaMap= texture2D(m_DiffuseMap, texCoord * m_DiffuseMap_0_scale).a;
float alpha = alphaMap*calculateAlphaBlend(alphaBlend.r, alphaMap);
#ifdef DIFFUSEMAP_1
alphaMap = texture2D(m_DiffuseMap_1, texCoord * m_DiffuseMap_1_scale).a;
alpha = mix( alpha, alphaMap, calculateAlphaBlend(alphaBlend.g, alphaMap));
#ifdef DIFFUSEMAP_2
alphaMap = texture2D(m_DiffuseMap_2, texCoord * m_DiffuseMap_2_scale).a;
alpha = mix( alpha, alphaMap, calculateAlphaBlend(alphaBlend.b, alphaMap));
#ifdef DIFFUSEMAP_3
alphaMap = texture2D(m_DiffuseMap_3, texCoord * m_DiffuseMap_3_scale).a;
alpha = mix( alpha, alphaMap, calculateAlphaBlend(alphaBlend.a, alphaMap));
#ifdef DIFFUSEMAP_4
alphaMap = texture2D(m_DiffuseMap_4, texCoord * m_DiffuseMap_4_scale).a;
alpha = mix( alpha, alphaMap, calculateAlphaBlend(alphaBlend1.r, alphaMap));
#ifdef DIFFUSEMAP_5
alphaMap = texture2D(m_DiffuseMap_5, texCoord * m_DiffuseMap_5_scale).a;
alpha = mix( alpha, alphaMap, calculateAlphaBlend(alphaBlend1.g, alphaMap));
#ifdef DIFFUSEMAP_6
alphaMap = texture2D(m_DiffuseMap_6, texCoord * m_DiffuseMap_6_scale).a;
alpha = mix( alpha, alphaMap, calculateAlphaBlend(alphaBlend1.b, alphaMap));
#ifdef DIFFUSEMAP_7
alphaMap = texture2D(m_DiffuseMap_7, texCoord * m_DiffuseMap_7_scale).a;
alpha = mix( alpha, alphaMap, calculateAlphaBlend(alphaBlend1.a, alphaMap));
#ifdef DIFFUSEMAP_8
alphaMap = texture2D(m_DiffuseMap_8, texCoord * m_DiffuseMap_8_scale).a;
alpha = mix( alpha, alphaMap, calculateAlphaBlend(alphaBlend2.r, alphaMap));
#ifdef DIFFUSEMAP_9
alphaMap = texture2D(m_DiffuseMap_9, texCoord * m_DiffuseMap_9_scale).a;
alpha = mix( alpha, alphaMap, calculateAlphaBlend(alphaBlend2.g, alphaMap));
#ifdef DIFFUSEMAP_10
alphaMap = texture2D(m_DiffuseMap_10, texCoord * m_DiffuseMap_10_scale).a;
alpha = mix( alpha, alphaMap, calculateAlphaBlend(alphaBlend2.b, alphaMap));
#ifdef DIFFUSEMAP_11
alphaMap = texture2D(m_DiffuseMap_11, texCoord * m_DiffuseMap_11_scale).a;
alpha = mix( alpha, alphaMap, calculateAlphaBlend(alphaBlend2.a, alphaMap));
#endif
#endif
#endif
#endif
#endif
#endif
#endif
#endif
#endif
#endif
#endif
return min(alpha*1.2,1.0);
}
#ifdef STEEPPARALLAX
vec2 steepParallaxOffset(vec3 vViewDir,vec2 texCoord){//,float parallaxScale){
// Test if the first value found is already at the highest value;
float fCurrHeight = sampleHeight(texCoord);
if (fCurrHeight > 1.0){
return texCoord;
}
vViewDir.y *= -1.0;
vec2 vParallaxDirection = normalize( vViewDir.xy );
// The length of this vector determines the furthest amount of displacement: (Ati's comment)
float fLength = length( vViewDir );
float fParallaxLength = sqrt( fLength * fLength - vViewDir.z * vViewDir.z ) / vViewDir.z;
// Compute the actual reverse parallax displacement vector: (Ati's comment)
vec2 vParallaxOffsetTS = vParallaxDirection * fParallaxLength;
// Need to scale the amount of displacement to account for different height ranges
// in height maps. This is controlled by an artist-editable parameter: (Ati's comment)
//parallaxScale *=0.3;
vParallaxOffsetTS *= m_ParallaxHeight;
vec3 eyeDir = normalize(vViewDir).xyz;
float nMinSamples = 1.0;
float nMaxSamples = m_ParallaxSamples; //* parallaxScale;
float nNumSamples = mix( nMinSamples, nMaxSamples, 1.0 - eyeDir.z ); //In reference shader: int nNumSamples = (int)(lerp( nMinSamples, nMaxSamples, dot( eyeDirWS, N ) ));
float fStepSize = 1.0 / nNumSamples;
float fPrevHeight = 1.0;
float fNextHeight = 0.0;
float nStepIndex = 0.0;
vec2 vTexOffsetPerStep = fStepSize * vParallaxOffsetTS;
vec2 vTexCurrentOffset = texCoord;
float fCurrentBound = 1.0;
float fParallaxAmount = 0.0;
while ( nStepIndex < nNumSamples && fCurrHeight < fCurrentBound ) {
vTexCurrentOffset -= vTexOffsetPerStep;
fPrevHeight = fCurrHeight;
// This line is changed specific for the terrain shader.
fCurrHeight = sampleHeight(vTexCurrentOffset);
fCurrentBound -= fStepSize;
nStepIndex+=1.0;
}
vec2 pt1 = vec2( fCurrentBound, fCurrHeight );
vec2 pt2 = vec2( fCurrentBound + fStepSize, fPrevHeight );
float fDelta2 = pt2.x - pt2.y;
float fDelta1 = pt1.x - pt1.y;
float fDenominator = fDelta2 - fDelta1;
fParallaxAmount = (pt1.x * fDelta2 - pt2.x * fDelta1 ) / fDenominator;
vec2 vParallaxOffset = vParallaxOffsetTS * (1.0 - fParallaxAmount );
return texCoord - vParallaxOffset;
}
#else
vec2 classicParallaxOffset(vec3 vViewDir,vec2 texCoord){
float h=sampleHeight(texCoord);
float heightScale = m_ParallaxHeight;
float heightBias = heightScale* -0.6;
vViewDir.y *= -1.0;
vec3 normView = normalize(vViewDir);
h = (h * heightScale + heightBias) * normView.z;
return texCoord + (h * normView.xy);
}
#endif
#endif
void main(){
//----------------------
// diffuse calculations
//----------------------
#ifdef DIFFUSEMAP
#ifdef ALPHAMAP
#ifdef TRI_PLANAR_MAPPING
vec4 diffuseColor = calculateTriPlanarDiffuseBlend(wNormal, wVertex, texCoord);
#else
#if defined(PARALLAXMAPPING)&& defined(BLENDWITHALPHA)
#ifdef STEEPPARALLAX
texCoord = steepParallaxOffset(vViewDir, texCoord);
#else
texCoord = classicParallaxOffset(vViewDir, texCoord);
#endif
#endif
vec4 diffuseColor = calculateDiffuseBlend(texCoord);
#endif
#else
vec4 diffuseColor = texture2D(m_DiffuseMap, texCoord);
#endif
#else
vec4 diffuseColor = vec4(1.0);
#endif
float spotFallOff = 1.0;
if(g_LightDirection.w!=0.0){
vec3 L=normalize(lightVec.xyz);
vec3 spotdir = normalize(g_LightDirection.xyz);
float curAngleCos = dot(-L, spotdir);
float innerAngleCos = floor(g_LightDirection.w) * 0.001;
float outerAngleCos = fract(g_LightDirection.w);
float innerMinusOuter = innerAngleCos - outerAngleCos;
spotFallOff = (curAngleCos - outerAngleCos) / innerMinusOuter;
if(spotFallOff <= 0.0){
gl_FragColor = AmbientSum * diffuseColor;
return;
}else{
spotFallOff = clamp(spotFallOff, 0.0, 1.0);
}
}
//---------------------
// normal calculations
//---------------------
#if defined(NORMALMAP) || defined(NORMALMAP_1) || defined(NORMALMAP_2) || defined(NORMALMAP_3) || defined(NORMALMAP_4) || defined(NORMALMAP_5) || defined(NORMALMAP_6) || defined(NORMALMAP_7) || defined(NORMALMAP_8) || defined(NORMALMAP_9) || defined(NORMALMAP_10) || defined(NORMALMAP_11)
#ifdef TRI_PLANAR_MAPPING
vec3 normal = calculateNormalTriPlanar(wNormal, wVertex, texCoord);
#else
vec3 normal = calculateNormal(texCoord);
#endif
#else
vec3 normal = vNormal;
#endif
//-----------------------
// lighting calculations
//-----------------------
vec4 lightDir = vLightDir;
lightDir.xyz = normalize(lightDir.xyz);
vec2 light = computeLighting(vPosition, normal, vViewDir.xyz, lightDir.xyz)*spotFallOff;
vec4 specularColor = vec4(1.0);
//--------------------------
// final color calculations
//--------------------------
gl_FragColor = AmbientSum * diffuseColor +
DiffuseSum * diffuseColor * light.x +
SpecularSum * specularColor * light.y;
//gl_FragColor.a = alpha;
}
[/java]
While working on this I noticed two bugs the first one was caused by using a normal map for one terrain texture and the combined normal map wasn’t being normalized correctly.
Bugged Screenshot:
The other one was with ParallaxMapping the depth looked like it was shifted in the wrong direction (Screenshots were taken from the parallax mapping sample in the default jMonkey tests)
I needed to flip vViewDir: “vViewDir.y *= -1.0;” but I’m not sure why I needed to do this (I mean it fits the way the bug looks, but seems still kind of odd to me).
Bugged Screenshot:
PS: The terrain shader is one ugly monstrosity there is “#ifdef” everywhere and if you change something you have to copy & paste it to a thousand places.