Sfoglia il codice sorgente

Merge branch 'master' of https://github.com/BabylonJS/Babylon.js

David Catuhe 9 anni fa
parent
commit
3e92f983ce

+ 0 - 22
Tools/NormalHeightMapTool/NormalHeightMapTool.sln

@@ -1,22 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 14
-VisualStudioVersion = 14.0.24720.0
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NormalHeightMapTool", "NormalHeightMapTool\NormalHeightMapTool.csproj", "{2F997E8B-E471-4703-AD73-366BB48AB825}"
-EndProject
-Global
-	GlobalSection(SolutionConfigurationPlatforms) = preSolution
-		Debug|Any CPU = Debug|Any CPU
-		Release|Any CPU = Release|Any CPU
-	EndGlobalSection
-	GlobalSection(ProjectConfigurationPlatforms) = postSolution
-		{2F997E8B-E471-4703-AD73-366BB48AB825}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-		{2F997E8B-E471-4703-AD73-366BB48AB825}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{2F997E8B-E471-4703-AD73-366BB48AB825}.Release|Any CPU.ActiveCfg = Release|Any CPU
-		{2F997E8B-E471-4703-AD73-366BB48AB825}.Release|Any CPU.Build.0 = Release|Any CPU
-	EndGlobalSection
-	GlobalSection(SolutionProperties) = preSolution
-		HideSolutionNode = FALSE
-	EndGlobalSection
-EndGlobal

+ 0 - 6
Tools/NormalHeightMapTool/NormalHeightMapTool/App.config

@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<configuration>
-    <startup> 
-        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
-    </startup>
-</configuration>

+ 0 - 66
Tools/NormalHeightMapTool/NormalHeightMapTool/NormalHeightMapTool.csproj

@@ -1,66 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
-  <PropertyGroup>
-    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
-    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
-    <ProjectGuid>{2F997E8B-E471-4703-AD73-366BB48AB825}</ProjectGuid>
-    <OutputType>Exe</OutputType>
-    <AppDesignerFolder>Properties</AppDesignerFolder>
-    <RootNamespace>NormalHeightMapTool</RootNamespace>
-    <AssemblyName>NormalHeightMapTool</AssemblyName>
-    <TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
-    <FileAlignment>512</FileAlignment>
-    <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
-    <PlatformTarget>AnyCPU</PlatformTarget>
-    <DebugSymbols>true</DebugSymbols>
-    <DebugType>full</DebugType>
-    <Optimize>false</Optimize>
-    <OutputPath>bin\Debug\</OutputPath>
-    <DefineConstants>DEBUG;TRACE</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
-    <PlatformTarget>AnyCPU</PlatformTarget>
-    <DebugType>pdbonly</DebugType>
-    <Optimize>true</Optimize>
-    <OutputPath>bin\Release\</OutputPath>
-    <DefineConstants>TRACE</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-  </PropertyGroup>
-  <ItemGroup>
-    <Reference Include="ImageProcessor, Version=2.3.2.0, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\packages\ImageProcessor.2.3.2.0\lib\net45\ImageProcessor.dll</HintPath>
-      <Private>True</Private>
-    </Reference>
-    <Reference Include="System" />
-    <Reference Include="System.Core" />
-    <Reference Include="System.Drawing" />
-    <Reference Include="System.Xml.Linq" />
-    <Reference Include="System.Data.DataSetExtensions" />
-    <Reference Include="Microsoft.CSharp" />
-    <Reference Include="System.Data" />
-    <Reference Include="System.Net.Http" />
-    <Reference Include="System.Xml" />
-  </ItemGroup>
-  <ItemGroup>
-    <Compile Include="Program.cs" />
-    <Compile Include="Properties\AssemblyInfo.cs" />
-  </ItemGroup>
-  <ItemGroup>
-    <None Include="App.config" />
-    <None Include="packages.config" />
-  </ItemGroup>
-  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
-  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
-       Other similar extension points exist, see Microsoft.Common.targets.
-  <Target Name="BeforeBuild">
-  </Target>
-  <Target Name="AfterBuild">
-  </Target>
-  -->
-</Project>

+ 0 - 276
Tools/NormalHeightMapTool/NormalHeightMapTool/Program.cs

@@ -1,276 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Drawing;
-using System.Drawing.Imaging;
-using System.IO;
-using System.Linq;
-using ImageProcessor;
-
-namespace NormalHeightMapTool
-{
-	class Program
-	{
-		private static List<Tuple<string, string>> _switches;
-
-		static void Main(string[] args)
-		{
-			// Display Help
-			if (args.Length == 0 || args.Any(a => string.Compare(a, "-h", StringComparison.InvariantCultureIgnoreCase) == 0))
-			{
-				DisplayUsage();
-				return;
-			}
-
-			// Construct a switch list, items1 of tuple is lowercast switch value without the dash, item2 is the value (if any)
-			if (BuildSwitches(args) == false)
-			{
-				DisplayUsage();
-				return;
-			}
-
-			// Check for pack operation
-			if (_switches[0].Item1 == "pack")
-			{
-				Pack();
-			}
-
-			// Check for invert operation
-			else if (_switches[0].Item1 == "invert")
-			{
-				Invert();
-			}
-
-			// Not either one of them, display usage and quit
-			else
-			{
-				DisplayUsage();
-				return;
-			}
-		}
-
-		private static bool BuildSwitches(string[] args)
-		{
-			_switches = new List<Tuple<string, string>>();
-			foreach (var a in args)
-			{
-				if (string.IsNullOrWhiteSpace(a) || a[0] != '-')
-				{
-					return false;
-				}
-
-				var sep = a.IndexOf(":", StringComparison.Ordinal);
-				if (sep == -1)
-				{
-					_switches.Add(new Tuple<string, string>(a.Substring(1).ToLowerInvariant(), null));
-				}
-				else
-				{
-					_switches.Add(new Tuple<string, string>(a.Substring(1, sep - 1).ToLowerInvariant(), a.Substring(sep + 1)));
-				}
-			}
-			return true;
-		}
-
-		private static void Invert()
-		{
-			var pfn = _switches[0].Item2;
-			if (File.Exists(pfn) == false)
-			{
-				Console.WriteLine("Can't find file: " + pfn + "\r\nSorry...");
-				return;
-			}
-
-			var saveSwitch = _switches.FirstOrDefault(s => s.Item1 == "save");
-			if (saveSwitch == null || string.IsNullOrWhiteSpace(saveSwitch.Item2))
-			{
-				Console.WriteLine("Must contain a -save:<targetfilepathname> to save the file.Sorry...");
-				return;
-			}
-
-			try
-			{
-				var invertR = _switches.Any(s => s.Item1=="r");
-				var invertG = _switches.Any(s => s.Item1=="g");
-
-				var fileData = File.ReadAllBytes(pfn);
-				using (var stream = new MemoryStream(fileData))
-				{
-					using (var factory = new ImageFactory())
-					{
-						factory.Load(stream);
-						var img = (Bitmap)factory.Image;
-						if (img == null)
-						{
-							Console.WriteLine("Unsupported file format or corrupted. Sorry...");
-							return;
-						}
-
-						Console.WriteLine("Working...");
-						for (int y = 0; y < img.Height; y++)
-						{
-							for (int x = 0; x < img.Width; x++)
-							{
-								var p = img.GetPixel(x, y);
-
-								var r = (invertR) ? (255 - p.R) : p.R;		// This is the invert operation on R
-								var g = (invertG) ? (255 - p.G) : p.G;		//  and G...
-								
-								var np = Color.FromArgb(p.A, r, g, p.B);
-
-								img.SetPixel(x, y, np);
-
-							}
-						}
-
-						Console.WriteLine("Saving to: " + saveSwitch.Item2);
-						var spfn = saveSwitch.Item2;
-						if (string.IsNullOrWhiteSpace(Path.GetDirectoryName(spfn)))
-						{
-							spfn = Path.Combine(Directory.GetCurrentDirectory(), spfn);
-						}
-						factory.Save(spfn);
-						Console.WriteLine("Job's done! Bye...");
-					}
-				}
-			}
-			catch (Exception ex)
-			{
-				Console.WriteLine("OOOOOOOPS\r\n\r\n" + ex.ToString());
-				return;
-			}
-		}
-
-		private static void Pack()
-		{
-			var nswitch = _switches.FirstOrDefault(s => s.Item1=="normalmap");
-			if (nswitch == null || string.IsNullOrWhiteSpace(nswitch.Item2) || File.Exists(nswitch.Item2) == false)
-			{
-				Console.WriteLine("You have to specify a valid file for -normalmap. Sorry...");
-				return;
-			}
-
-			var hswitch = _switches.FirstOrDefault(s => s.Item1=="heightmap");
-			if (hswitch == null || string.IsNullOrWhiteSpace(hswitch.Item2) || File.Exists(hswitch.Item2) == false)
-			{
-				Console.WriteLine("You have to specify a valid file for -heightmap. Sorry...");
-				return;
-			}
-
-			var saveSwitch = _switches.FirstOrDefault(s => s.Item1 == "save");
-			if (saveSwitch == null || string.IsNullOrWhiteSpace(saveSwitch.Item2))
-			{
-				Console.WriteLine("Must contain a -save:<targetfilepathname> to save the file.Sorry...");
-				return;
-			}
-
-			var cswitch = _switches.FirstOrDefault(s => s.Item1=="heightmapchannel");
-			var channel = "r";
-			if (cswitch != null)
-			{
-				channel = cswitch.Item2.ToLowerInvariant();
-				switch (channel)
-				{
-					case "a":
-					case "r":
-					case "g":
-					case "b":
-						break;
-					default:
-						Console.WriteLine("You didn't specify a valid channel, only A, R, G, B are valid. Sorry...");
-						return;
-				}
-			}
-
-			var normalFileData = File.ReadAllBytes(nswitch.Item2);
-			var heightFileData = File.ReadAllBytes(hswitch.Item2);
-
-			using (var normalStream = new MemoryStream(normalFileData))
-			using (var heightStream = new MemoryStream(heightFileData))
-			{
-				using (var normalFactory = new ImageFactory()) 
-				using (var heightFactory = new ImageFactory()) 
-				{
-					normalFactory.Load(normalStream);
-					heightFactory.Load(heightStream);
-
-					var normalImg = (Bitmap)normalFactory.Image;
-					var heightImg = (Bitmap)heightFactory.Image;
-
-					if (normalImg.PixelFormat != PixelFormat.Format32bppArgb && normalImg.PixelFormat != PixelFormat.Format32bppPArgb)
-					{
-						Console.WriteLine("The normalmap source file must be argb, sorry lazy me doesn't suport rgb only...");
-						return;
-					}
-
-					try
-					{
-						Console.WriteLine("Working...");
-						for (int y = 0; y < normalImg.Height; y++)
-						{
-							for (int x = 0; x < normalImg.Width; x++)
-							{
-								var normalPix = normalImg.GetPixel(x, y);
-								var heightPix = heightImg.GetPixel(x, y);
-
-								int alpha;
-								switch (channel)
-								{
-									case "a":
-										alpha = heightPix.A;
-										break;
-									case "r":
-										alpha = heightPix.R;
-										break;
-									case "g":
-										alpha = heightPix.G;
-										break;
-									case "b":
-										alpha = heightPix.B;
-										break;
-									default:
-										alpha = heightPix.R;
-										break;
-								}
-
-								var newPixel = Color.FromArgb(alpha<<24 | (normalPix.ToArgb()&0XFFFFFF));
-								normalImg.SetPixel(x, y, newPixel);
-							}
-						}
-						Console.WriteLine("Saving to: " + saveSwitch.Item2);
-
-						var spfn = saveSwitch.Item2;
-						if (string.IsNullOrWhiteSpace(Path.GetDirectoryName(spfn)))
-						{
-							spfn = Path.Combine(Directory.GetCurrentDirectory(), spfn);
-						}
-						normalFactory.Save(spfn);
-						Console.WriteLine("Job's done! Bye...");
-					}
-					catch (Exception ex)
-					{
-						Console.WriteLine("OOOOOOOPS\r\n\r\n" + ex.ToString());
-						return;
-					}
-				}
-			}
-		}
-
-		public static void DisplayUsage()
-		{
-				var helpMessage = 
-@"
-Normal/HeightMap Tool
-=====================
-
-Usage:
- To pack a normal map file and a height map file in one single file (height map will be stored in alpha channel and the value will be taken in the Red component of the source heightmap if -heightmapchannel is not specified):
- -pack -normalmap:<filepathname> -heightmap:<filepathname> [-heightmapchannel:R|G|B|A] -save:<targetfilepathname>
-
- To invert the R &| G component of a normal map:
- -invert:<normalmapfilepathname> [-R] [-G] -save:<targetfilepathname>
-
-";
-			Console.WriteLine(helpMessage);		
-		}
-	}
-}

+ 0 - 36
Tools/NormalHeightMapTool/NormalHeightMapTool/Properties/AssemblyInfo.cs

@@ -1,36 +0,0 @@
-using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
-// General Information about an assembly is controlled through the following 
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
-[assembly: AssemblyTitle("NormalHeightMapTool")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("NormalHeightMapTool")]
-[assembly: AssemblyCopyright("Copyright ©  2016")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-
-// Setting ComVisible to false makes the types in this assembly not visible 
-// to COM components.  If you need to access a type in this assembly from 
-// COM, set the ComVisible attribute to true on that type.
-[assembly: ComVisible(false)]
-
-// The following GUID is for the ID of the typelib if this project is exposed to COM
-[assembly: Guid("2f997e8b-e471-4703-ad73-366bb48ab825")]
-
-// Version information for an assembly consists of the following four values:
-//
-//      Major Version
-//      Minor Version 
-//      Build Number
-//      Revision
-//
-// You can specify all the values or you can default the Build and Revision Numbers 
-// by using the '*' as shown below:
-// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.0")]

+ 0 - 4
Tools/NormalHeightMapTool/NormalHeightMapTool/packages.config

@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<packages>
-  <package id="ImageProcessor" version="2.3.2.0" targetFramework="net452" />
-</packages>

+ 0 - 25
Tools/NormalHeightMapTool/ReadMe.md

@@ -1,25 +0,0 @@
-Normal/Height Map Tool
-======================
-
-This little command line tool is used to perform these tasks:
-
-- Pack two distinct normal map and height map files into a single one, store the height in the alpha channel.
-
-- Perform Color based invert on R and/or G channel of a normal map to reoriente the normal vector.
-
-You can find a single .exe file in the Redist folder, if you build the project beware that the ImageProcessor.dll must be merged or bring along with the exe.
-
-
-### Command line usage:
-```
- To pack a normal map file and a height map file in one single file (height map will be stored in alpha channel and the value will be taken in the Red component of the source heightmap if -heightmapchannel is not specified):
- -pack -normalmap:<filepathname> -heightmap:<filepathname> [-heightmapchannel:R|G|B|A] -save:<targetfilepathname>
-
- To invert the R &| G component of a normal map:
- -invert:<normalmapfilepathname> [-R] [-G] -save:<targetfilepathname>
-```
-
-### Acknowledgement
-This tool use the [ImageProcessor library](http://imageprocessor.org/)
-
-Exe+dll are merged thanks to [ILMerge-GUI](http://ilmergegui.codeplex.com//)

BIN
Tools/NormalHeightMapTool/Redist/NormalHeightMapTool.exe


+ 2 - 1
materialsLibrary/materials/pbr/pbr.fragment.fx

@@ -797,7 +797,8 @@ void main(void) {
 
 
     #ifdef BUMP
-        normalW = perturbNormal(viewDirectionW);
+		mat3 TBN = cotangent_frame(vNormalW * vBumpInfos.y, -viewDirectionW, vBumpUV);
+		normalW = perturbNormal(viewDirectionW, TBN, vBumpUV);
     #endif
 
     // Ambient color

File diff suppressed because it is too large
+ 857 - 830
src/Materials/babylon.standardMaterial.js


+ 32 - 2
src/Materials/babylon.standardMaterial.ts

@@ -8,6 +8,8 @@
         public EMISSIVE = false;
         public SPECULAR = false;
         public BUMP = false;
+        public PARALLAX = false;
+        public PARALLAXOCCLUSION = false;
         public SPECULAROVERALPHA = false;
         public CLIPPLANE = false;
         public ALPHATEST = false;
@@ -155,6 +157,15 @@
         public disableLighting = false;
 
         @serialize()
+        public useParallax = false;
+
+        @serialize()
+        public useParallaxOcclusion = false;
+
+        @serialize()
+        public parallaxScaleBias = 0.05;
+
+        @serialize()
         public roughness = 0;
 
         @serialize()
@@ -398,6 +409,13 @@
                     } else {
                         needUVs = true;
                         this._defines.BUMP = true;
+
+                        if (this.useParallax) {
+                            this._defines.PARALLAX = true;
+                            if (this.useParallaxOcclusion) {
+                                this._defines.PARALLAXOCCLUSION = true;
+                            }
+                        }
                     }
                 }
 
@@ -544,6 +562,14 @@
                     fallbacks.addFallback(0, "BUMP");
                 }
 
+                if (this._defines.PARALLAX) {
+                    fallbacks.addFallback(1, "PARALLAX");
+                }
+
+                if (this._defines.PARALLAXOCCLUSION) {
+                    fallbacks.addFallback(0, "PARALLAXOCCLUSION");
+                }
+
                 if (this._defines.SPECULAROVERALPHA) {
                     fallbacks.addFallback(0, "SPECULAROVERALPHA");
                 }
@@ -622,7 +648,7 @@
                         "vLightData2", "vLightDiffuse2", "vLightSpecular2", "vLightDirection2", "vLightGround2", "lightMatrix2",
                         "vLightData3", "vLightDiffuse3", "vLightSpecular3", "vLightDirection3", "vLightGround3", "lightMatrix3",
                         "vFogInfos", "vFogColor", "pointSize",
-                        "vDiffuseInfos", "vAmbientInfos", "vOpacityInfos", "vReflectionInfos", "vEmissiveInfos", "vSpecularInfos", "vBumpInfos", "vLightmapInfos", "vRefractionInfos",
+                        "vDiffuseInfos", "vAmbientInfos", "vOpacityInfos", "vReflectionInfos", "vEmissiveInfos", "vSpecularInfos", "vBumpInfos", "vParallaxScaleBias", "vLightmapInfos", "vRefractionInfos",
                         "mBones",
                         "vClipPlane", "diffuseMatrix", "ambientMatrix", "opacityMatrix", "reflectionMatrix", "emissiveMatrix", "specularMatrix", "bumpMatrix", "lightmapMatrix", "refractionMatrix",
                         "shadowsInfo0", "shadowsInfo1", "shadowsInfo2", "shadowsInfo3", "depthValues",
@@ -766,8 +792,12 @@
                     if (this.bumpTexture && scene.getEngine().getCaps().standardDerivatives && StandardMaterial.BumpTextureEnabled) {
                         this._effect.setTexture("bumpSampler", this.bumpTexture);
 
-                        this._effect.setFloat2("vBumpInfos", this.bumpTexture.coordinatesIndex, 1.0 / this.bumpTexture.level);
+                        this._effect.setFloat3("vBumpInfos", this.bumpTexture.coordinatesIndex, 1.0 / this.bumpTexture.level, this.parallaxScaleBias);
                         this._effect.setMatrix("bumpMatrix", this.bumpTexture.getTextureMatrix());
+
+                        if (this.useParallax) {
+                            this._effect.setFloat("vParallaxScaleBias", this.parallaxScaleBias);
+                        }
                     }
 
                     if (this.refractionTexture && StandardMaterial.RefractionTextureEnabled) {

+ 70 - 5
src/Shaders/ShadersInclude/bumpFragmentFunctions.fx

@@ -1,6 +1,6 @@
 #ifdef BUMP
 	varying vec2 vBumpUV;
-	uniform vec2 vBumpInfos;
+	uniform vec3 vBumpInfos;
 	uniform sampler2D bumpSampler;
 
 	// Thanks to http://www.thetenthplanet.de/archives/1180
@@ -23,11 +23,76 @@
 		return mat3(tangent * invmax, binormal * invmax, normal);
 	}
 
-	vec3 perturbNormal(vec3 viewDir)
+	vec3 perturbNormal(vec3 viewDir, mat3 cotangentFrame, vec2 uv)
 	{
-		vec3 map = texture2D(bumpSampler, vBumpUV).xyz;
+		vec3 map = texture2D(bumpSampler, uv).xyz;
 		map = map * 255. / 127. - 128. / 127.;
-		mat3 TBN = cotangent_frame(vNormalW * vBumpInfos.y, -viewDir, vBumpUV);
-		return normalize(TBN * map);
+		return normalize(cotangentFrame * map);
 	}
+
+#ifdef PARALLAX
+	const float minSamples = 4.;
+	const float maxSamples = 15.;
+	const int iMaxSamples = 15;
+
+	// http://www.gamedev.net/page/resources/_/technical/graphics-programming-and-theory/a-closer-look-at-parallax-occlusion-mapping-r3262
+	vec2 parallaxOcclusion(vec3 vViewDirCoT, vec3 vNormalCoT, vec2 texCoord, float parallaxScale) {
+
+		float parallaxLimit = length(vViewDirCoT.xy) / vViewDirCoT.z;
+		parallaxLimit *= parallaxScale;
+		vec2 vOffsetDir = normalize(vViewDirCoT.xy);
+		vec2 vMaxOffset = vOffsetDir * parallaxLimit;
+		float numSamples = maxSamples + (dot(vViewDirCoT, vNormalCoT) * (minSamples - maxSamples));
+		float stepSize = 1.0 / numSamples;
+
+		// Uncomment whevener GL_EXT_shader_texture_lod with texture2DGradEXT will work
+		//vec2 dx = dFdx(vBumpUV);
+		//vec2 dy = dFdy(vBumpUV);
+
+		// Initialize the starting view ray height and the texture offsets.
+		float currRayHeight = 1.0;
+		vec2 vCurrOffset = vec2(0, 0);
+		vec2 vLastOffset = vec2(0, 0);
+
+		float lastSampledHeight = 1.0;
+		float currSampledHeight = 1.0;
+
+		for (int i = 0; i < iMaxSamples; i++)
+		{
+			currSampledHeight = texture2D(bumpSampler, vBumpUV + vCurrOffset).w;
+
+			// Test if the view ray has intersected the surface.
+			if (currSampledHeight > currRayHeight)
+			{
+				float delta1 = currSampledHeight - currRayHeight;
+				float delta2 = (currRayHeight + stepSize) - lastSampledHeight;
+				float ratio = delta1 / (delta1 + delta2);
+				vCurrOffset = (ratio)* vLastOffset + (1.0 - ratio) * vCurrOffset;
+
+				// Force the exit of the loop
+				break;
+			}
+			else
+			{
+				currRayHeight -= stepSize;
+				vLastOffset = vCurrOffset;
+				vCurrOffset += stepSize * vMaxOffset;
+
+				lastSampledHeight = currSampledHeight;
+			}
+		}
+
+		return vCurrOffset;
+	}
+
+	vec2 parallaxOffset(vec3 viewDir, float heightScale)
+	{
+		// calculate amount of offset for Parallax Mapping With Offset Limiting
+		float height = texture2D(bumpSampler, vBumpUV).w;
+		vec2 texCoordOffset = heightScale * viewDir.xy * height;
+		return -texCoordOffset;
+	}
+
+#endif
+
 #endif

+ 14 - 0
src/Shaders/ShadersInclude/helperFunctions.fx

@@ -0,0 +1,14 @@
+
+mat3 transposeMat3(mat3 inMatrix) {
+	vec3 i0 = inMatrix[0];
+	vec3 i1 = inMatrix[1];
+	vec3 i2 = inMatrix[2];
+
+	mat3 outMatrix = mat3(
+		vec3(i0.x, i1.x, i2.x),
+		vec3(i0.y, i1.y, i2.y),
+		vec3(i0.z, i1.z, i2.z)
+		);
+
+	return outMatrix;
+}

+ 53 - 14
src/Shaders/default.fragment.fx

@@ -1,4 +1,8 @@
-#ifdef BUMP
+#ifdef PARALLAX
+//#extension GL_EXT_shader_texture_lod : enable		// Doesn't work right now with texture2DGradExt...
+#endif
+
+#ifdef BUMP
 #extension GL_OES_standard_derivatives : enable
 #endif
 
@@ -30,6 +34,9 @@ varying vec3 vNormalW;
 varying vec4 vColor;
 #endif
 
+// Helper functions
+#include<helperFunctions>
+
 // Lights
 #include<light0FragmentDeclaration>
 #include<light1FragmentDeclaration>
@@ -161,8 +168,52 @@ void main(void) {
 	// Alpha
 	float alpha = vDiffuseColor.a;
 
+	// Bump
+#ifdef NORMAL
+	vec3 normalW = normalize(vNormalW);
+#else
+	vec3 normalW = vec3(1.0, 1.0, 1.0);
+#endif
+
+#ifdef DIFFUSE
+	vec2 diffuseUV = vDiffuseUV;
+#endif
+
+#ifdef BUMP
+	vec2 bumpUV = vBumpUV;
+#endif
+
+#if defined(BUMP) || defined(PARALLAX)
+	mat3 TBN = cotangent_frame(normalW * vBumpInfos.y, -viewDirectionW, bumpUV);
+#endif
+
+#ifdef PARALLAX
+	mat3 invTBN = transposeMat3(TBN);
+
+#ifdef PARALLAXOCCLUSION
+	vec2 uvOffset = parallaxOcclusion(invTBN * -viewDirectionW, invTBN * normalW, bumpUV, vBumpInfos.z);
+#else
+	vec2 uvOffset = parallaxOffset(invTBN * viewDirectionW, vBumpInfos.z);
+#endif
+
+	diffuseUV += uvOffset;
+	bumpUV += uvOffset;
+
+	// Note by Loic: won't be nice with wrapping textures...
+#ifdef PARALLAXOCCLUSION
+	if (diffuseUV.x > 1.0 || diffuseUV.y > 1.0 || diffuseUV.x < 0.0 || diffuseUV.y < 0.0) {
+		discard;
+	}
+#endif
+
+#endif
+
+#ifdef BUMP
+	normalW = perturbNormal(viewDirectionW, TBN, bumpUV);
+#endif
+
 #ifdef DIFFUSE
-	baseColor = texture2D(diffuseSampler, vDiffuseUV);
+	baseColor = texture2D(diffuseSampler, diffuseUV);
 
 #ifdef ALPHATEST
 	if (baseColor.a < 0.4)
@@ -180,18 +231,6 @@ void main(void) {
 	baseColor.rgb *= vColor.rgb;
 #endif
 
-	// Bump
-#ifdef NORMAL
-	vec3 normalW = normalize(vNormalW);
-#else
-	vec3 normalW = vec3(1.0, 1.0, 1.0);
-#endif
-
-
-#ifdef BUMP
-	normalW = perturbNormal(viewDirectionW);
-#endif
-
 	// Ambient color
 	vec3 baseAmbientColor = vec3(1., 1., 1.);
 

+ 1 - 1
src/Shaders/default.vertex.fx

@@ -61,7 +61,7 @@ uniform mat4 specularMatrix;
 
 #ifdef BUMP
 varying vec2 vBumpUV;
-uniform vec2 vBumpInfos;
+uniform vec3 vBumpInfos;
 uniform mat4 bumpMatrix;
 #endif