Browse Source

Merge pull request #1580 from fallahn/next

Add water sample to browser
Sean Taylor 11 years ago
parent
commit
ec6932e9f1

+ 7 - 1
gameplay/res/shaders/colored.frag

@@ -93,10 +93,16 @@ varying vec3 v_cameraDirection;
 
 #endif
 
+#if defined(CLIP_PLANE)
+varying float v_clipDistance;
+#endif
 
 void main()
 {
-    
+    #if defined(CLIP_PLANE)
+    if(v_clipDistance < 0.0) discard;
+    #endif
+ 
     #if defined(LIGHTING)
 
     #if defined(VERTEX_COLOR)

+ 12 - 0
gameplay/res/shaders/colored.vert

@@ -66,6 +66,11 @@ uniform vec3 u_cameraPosition;
 
 #endif
 
+#if defined(CLIP_PLANE)
+uniform mat4 u_worldMatrix;
+uniform vec4 u_clipPlane;
+#endif
+
 ///////////////////////////////////////////////////////////
 // Varyings
 #if defined(LIGHTMAP)
@@ -106,6 +111,9 @@ varying vec3 v_cameraDirection;
 #include "skinning-none.vert" 
 #endif
 
+#if defined(CLIP_PLANE)
+varying float v_clipDistance;
+#endif
 
 void main()
 {
@@ -134,4 +142,8 @@ void main()
     #if defined(VERTEX_COLOR)
 	v_color = a_color;
     #endif
+    
+    #if defined(CLIP_PLANE)
+    v_clipDistance = dot(u_worldMatrix * position, u_clipPlane);
+    #endif    
 }

+ 8 - 0
gameplay/res/shaders/textured.frag

@@ -113,9 +113,17 @@ varying vec3 v_cameraDirection;
 
 #endif
 
+#if defined(CLIP_PLANE)
+varying float v_clipDistance;
+#endif
+
 
 void main()
 {
+    #if defined(CLIP_PLANE)
+    if(v_clipDistance < 0.0) discard;
+    #endif
+ 
     _baseColor = texture2D(u_diffuseTexture, v_texCoord);
  
     gl_FragColor.a = _baseColor.a;

+ 13 - 0
gameplay/res/shaders/textured.vert

@@ -79,6 +79,11 @@ uniform vec2 u_textureRepeat;
 uniform vec2 u_textureOffset;
 #endif
 
+#if defined(CLIP_PLANE)
+uniform mat4 u_worldMatrix;
+uniform vec4 u_clipPlane;
+#endif
+
 ///////////////////////////////////////////////////////////
 // Varyings
 varying vec2 v_texCoord;
@@ -122,6 +127,10 @@ varying vec3 v_cameraDirection;
 #include "skinning-none.vert" 
 #endif
 
+#if defined(CLIP_PLANE)
+varying float v_clipDistance;
+#endif
+
 void main()
 {
     vec4 position = getPosition();
@@ -164,4 +173,8 @@ void main()
     #if defined(LIGHTMAP)
     v_texCoord1 = a_texCoord1;
     #endif
+    
+    #if defined(CLIP_PLANE)
+    v_clipDistance = dot(u_worldMatrix * position, u_clipPlane);
+    #endif
 }

BIN
samples/browser/res/common/water/pond.gpb


BIN
samples/browser/res/common/water/water_normal.png


BIN
samples/browser/res/common/water/water_sample.png


+ 83 - 0
samples/browser/res/common/water/watersample.frag

@@ -0,0 +1,83 @@
+#ifdef OPENGL_ES
+precision mediump float;
+#endif
+
+//////////////////////////
+// Uniforms
+uniform sampler2D u_refractionTexture;
+uniform sampler2D u_reflectionTexture;
+
+uniform sampler2D u_normalMap;
+
+uniform float u_time;
+
+//////////////////////////
+// Varyings
+varying vec4 v_vertexRefractionPosition;
+varying vec4 v_vertexReflectionPosition;
+
+varying vec2 v_texCoord;
+
+varying vec3 v_eyePosition;
+
+//////////////////////////
+
+const float distortAmount = 0.05;
+const float specularAmount = 2.5;
+const float textureRepeat = 2.0;
+
+const vec4 tangent = vec4(1.0, 0.0, 0.0, 0.0);
+const vec4 viewNormal = vec4(0.0, 1.0, 0.0, 0.0);
+const vec4 bitangent = vec4(0.0, 0.0, 1.0, 0.0);
+
+const vec4 waterColour = vec4(0.36, 0.32, 0.2,1.0);
+
+vec2 fromClipSpace(vec4 position)
+{
+    return position.xy / position.w / 2.0 + 0.5;
+}
+
+void main()
+{	
+    //get normal
+    vec4 normal = texture2D(u_normalMap, v_texCoord * textureRepeat + u_time);
+    normal = normalize(normal * 2.0 - 1.0);
+    
+    //distortion offset
+    vec4 dudv = normal * distortAmount;
+
+    //refraction sample
+    vec2 textureCoord = fromClipSpace(v_vertexRefractionPosition) + dudv.rg;
+    textureCoord = clamp(textureCoord, 0.001, 0.999);
+    vec4 refractionColour = texture2D(u_refractionTexture, textureCoord) * waterColour;
+
+    //calc fog distance
+    //----version 1 (exponential)----//
+    //float z = gl_FragCoord.z / gl_FragCoord.w;
+    //const float fogDensity = 0.0005;
+    //float fogAmount = exp2(-fogDensity * fogDensity * z * z * 1.442695);
+    //fogAmount = clamp(fogAmount, 0.0, 0.7);
+
+    //----version 2 (linear)----//
+    float z = (gl_FragCoord.z / gl_FragCoord.w) / 300.0; //const is max fog distance
+    const float fogDensity = 6.0;
+    float fogAmount = z * fogDensity;	
+    fogAmount = clamp(fogAmount, 0.0, 1.0);
+
+    refractionColour = mix(refractionColour, waterColour, fogAmount);
+
+    //reflection sample
+    textureCoord = fromClipSpace(v_vertexReflectionPosition) + dudv.rg;
+    textureCoord = clamp(textureCoord, 0.001, 0.999);	
+    vec4 reflectionColour = texture2D(u_reflectionTexture, textureCoord);
+
+    //put view in tangent space
+    vec4 viewDir = normalize(vec4(v_eyePosition, 1.0));
+    vec4 viewTanSpace = normalize(vec4(dot(viewDir, tangent), dot(viewDir, bitangent), dot(viewDir, viewNormal), 1.0));	
+    vec4 viewReflection = normalize(reflect(-1.0 * viewTanSpace, normal));
+    float fresnel = dot(normal, viewReflection);	
+
+    vec3 specular = vec3(clamp(pow(dot(viewTanSpace, normal), 255.0), 0.0, 1.0)) * specularAmount;
+
+    gl_FragColor = mix(reflectionColour, refractionColour, fresnel) + vec4(specular, 1.0);
+}

+ 70 - 0
samples/browser/res/common/water/watersample.material

@@ -0,0 +1,70 @@
+material ground
+{
+    technique
+    {
+        pass
+        {
+            vertexShader = res/shaders/textured.vert
+            fragmentShader = res/shaders/textured.frag
+            defines = DIRECTIONAL_LIGHT_COUNT 1;CLIP_PLANE
+            
+            u_worldMatrix = WORLD_MATRIX
+            u_worldViewProjectionMatrix = WORLD_VIEW_PROJECTION_MATRIX
+            u_inverseTransposeWorldViewMatrix = INVERSE_TRANSPOSE_WORLD_VIEW_MATRIX
+            
+            u_ambientColor = SCENE_AMBIENT_COLOR
+	    u_directionalLightColor[0] = 1, 1, 1
+            
+            sampler u_diffuseTexture
+            {
+            	mipmap = true
+	    	wrapS = REPEAT
+	    	wrapT = REPEAT
+	    	minFilter = LINEAR_MIPMAP_LINEAR
+		magFilter = LINEAR
+		
+		path = res/common/water/water_sample.png
+            }
+            
+            renderState
+            {
+                cullFace = true
+                depthTest = true
+            }
+        }
+    }
+}
+
+material water
+{
+    technique
+    {
+
+        pass
+        {
+             vertexShader = res/common/water/watersample.vert
+             fragmentShader = res/common/water/watersample.frag
+
+             u_worldMatrix = WORLD_MATRIX
+             u_worldViewProjectionMatrix = WORLD_VIEW_PROJECTION_MATRIX
+             u_cameraPosition = CAMERA_WORLD_POSITION
+
+             sampler u_normalMap
+             {
+                 mipmap = true
+                 wrapS = REPEAT
+                 wrapT = REPEAT
+                 minFilter = LINEAR_MIPMAP_LINEAR
+                 magFilter = LINEAR
+
+                 path = res/common/water/water_normal.png
+             }
+
+             renderState
+             {
+                 cullFace = true
+                 depthTest = true
+             }
+         }
+     }
+}

+ 15 - 0
samples/browser/res/common/water/watersample.scene

@@ -0,0 +1,15 @@
+scene
+{
+    path = res/common/water/pond.gpb
+
+
+    node Ground
+    {
+        material = res/common/water/watersample.material#ground
+    }
+
+    node Water
+    {
+        material = res/common/water/watersample.material#water		
+    }    	
+}

+ 34 - 0
samples/browser/res/common/water/watersample.vert

@@ -0,0 +1,34 @@
+/////////////////////////////
+// Attributes
+attribute vec4 a_position;
+attribute vec2 a_texCoord;
+
+/////////////////////////////
+// Uniforms
+uniform mat4 u_worldMatrix;
+uniform mat4 u_worldViewProjectionMatrix;
+uniform mat4 u_worldViewProjectionReflectionMatrix;
+
+uniform vec3 u_cameraPosition;
+
+/////////////////////////////
+// Varyings
+varying vec4 v_vertexRefractionPosition;
+varying vec4 v_vertexReflectionPosition;
+
+varying vec2 v_texCoord;
+
+varying vec3 v_eyePosition;
+
+/////////////////////////////
+void main()
+{
+    v_vertexRefractionPosition = u_worldViewProjectionMatrix * a_position;
+    v_vertexReflectionPosition = u_worldViewProjectionReflectionMatrix * a_position;
+
+    gl_Position = v_vertexRefractionPosition;
+
+    v_texCoord = a_texCoord;
+
+    v_eyePosition = u_cameraPosition - (u_worldMatrix * a_position).xyz;
+}

+ 3 - 1
samples/browser/sample-browser.vcxproj

@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
 <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <ItemGroup Label="ProjectConfigurations">
     <ProjectConfiguration Include="DebugMem|x64">
@@ -273,6 +273,7 @@ copy ..\..\gameplay\res\logo_powered_white.png res</Command>
     <ClCompile Include="src\TextSample.cpp" />
     <ClCompile Include="src\TextureSample.cpp" />
     <ClCompile Include="src\MeshBatchSample.cpp" />
+    <ClCompile Include="src\WaterSample.cpp" />
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="src\Audio3DSample.h" />
@@ -297,6 +298,7 @@ copy ..\..\gameplay\res\logo_powered_white.png res</Command>
     <ClInclude Include="src\TextSample.h" />
     <ClInclude Include="src\TextureSample.h" />
     <ClInclude Include="src\MeshBatchSample.h" />
+    <ClInclude Include="src\WaterSample.h" />
   </ItemGroup>
   <ItemGroup>
     <Image Include="res\common\terrain\dirt.dds" />

+ 460 - 454
samples/browser/sample-browser.vcxproj.filters

@@ -1,455 +1,461 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <Filter Include="src">
-    </Filter>
-    <Filter Include="src\common">
-      <UniqueIdentifier>{c35d9ec0-a966-49e8-af48-14cbcb2d6818}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="res">
-      <UniqueIdentifier>{b0da65f8-9ff6-4813-9af3-3bb222d54acf}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="res\common">
-      <UniqueIdentifier>{6cb7d9bf-0b2d-44df-a48d-d8150c67f38c}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="res\png">
-      <UniqueIdentifier>{6a436bab-00f5-4c87-9e53-b360dba474c2}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="res\common\forms">
-      <UniqueIdentifier>{a3201c29-9b57-40a3-839e-e5b8ad1fe53d}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="res\common\terrain">
-      <UniqueIdentifier>{7486d723-ca70-4cf7-a8fb-034679fad89f}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="res\common\postprocess">
-      <UniqueIdentifier>{97b23ce2-184f-46f4-a2fc-11aca4473fb3}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="res\shaders">
-      <UniqueIdentifier>{e1543678-e81b-48de-b753-3d5f000fd70b}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="res\common\fonts">
-      <UniqueIdentifier>{10e17594-e3ef-49d2-a2a4-fb874c32b5c7}</UniqueIdentifier>
-    </Filter>
-  </ItemGroup>
-  <ItemGroup>
-    <None Include="game.config" />
-    <None Include="icon.png" />
-    <None Include="bar-descriptor.xml" />
-    <None Include="res\common\forms\formBasicControls.form">
-      <Filter>res\common\forms</Filter>
-    </None>
-    <None Include="res\common\forms\formFlowLayout.form">
-      <Filter>res\common\forms</Filter>
-    </None>
-    <None Include="res\common\forms\formScrolling.form">
-      <Filter>res\common\forms</Filter>
-    </None>
-    <None Include="res\common\forms\formSelect.form">
-      <Filter>res\common\forms</Filter>
-    </None>
-    <None Include="res\common\forms\formVerticalLayout.form">
-      <Filter>res\common\forms</Filter>
-    </None>
-    <None Include="res\common\forms\formZOrder.form">
-      <Filter>res\common\forms</Filter>
-    </None>
-    <None Include="res\common\postprocess\postprocess.material">
-      <Filter>res\common\postprocess</Filter>
-    </None>
-    <None Include="res\common\postprocess\postprocess.vert">
-      <Filter>res\common\postprocess</Filter>
-    </None>
-    <None Include="res\common\postprocess\postprocess_gaussianblur.frag">
-      <Filter>res\common\postprocess</Filter>
-    </None>
-    <None Include="res\common\postprocess\postprocess_grayscale.frag">
-      <Filter>res\common\postprocess</Filter>
-    </None>
-    <None Include="res\common\postprocess\postprocess_oldfilm.frag">
-      <Filter>res\common\postprocess</Filter>
-    </None>
-    <None Include="res\common\postprocess\postprocess_passthrough.frag">
-      <Filter>res\common\postprocess</Filter>
-    </None>
-    <None Include="res\common\postprocess\postprocess_pixelate.frag">
-      <Filter>res\common\postprocess</Filter>
-    </None>
-    <None Include="res\common\postprocess\postprocess_sepia.frag">
-      <Filter>res\common\postprocess</Filter>
-    </None>
-    <None Include="res\common\postprocess\postprocess_sobeledge.frag">
-      <Filter>res\common\postprocess</Filter>
-    </None>
-    <None Include="res\common\terrain\encode.bat">
-      <Filter>res\common\terrain</Filter>
-    </None>
-    <None Include="res\common\terrain\heightmap.r16">
-      <Filter>res\common\terrain</Filter>
-    </None>
-    <None Include="res\common\terrain\sample.scene">
-      <Filter>res\common\terrain</Filter>
-    </None>
-    <None Include="res\common\terrain\sample.terrain">
-      <Filter>res\common\terrain</Filter>
-    </None>
-    <None Include="res\common\terrain\shapes.material">
-      <Filter>res\common\terrain</Filter>
-    </None>
-    <None Include="res\common\terrain\sky.fbx">
-      <Filter>res\common\terrain</Filter>
-    </None>
-    <None Include="res\common\terrain\sky.gpb">
-      <Filter>res\common\terrain</Filter>
-    </None>
-    <None Include="res\common\terrain\sky.material">
-      <Filter>res\common\terrain</Filter>
-    </None>
-    <None Include="res\common\terrain\terrain.form">
-      <Filter>res\common\terrain</Filter>
-    </None>
-    <None Include="res\common\box.gpb">
-      <Filter>res\common</Filter>
-    </None>
-    <None Include="res\common\box.material">
-      <Filter>res\common</Filter>
-    </None>
-    <None Include="res\common\camera.lua">
-      <Filter>res\common</Filter>
-    </None>
-    <None Include="res\common\constraints.gpb">
-      <Filter>res\common</Filter>
-    </None>
-    <None Include="res\common\constraints.physics">
-      <Filter>res\common</Filter>
-    </None>
-    <None Include="res\common\constraints.scene">
-      <Filter>res\common</Filter>
-    </None>
-    <None Include="res\common\default.theme">
-      <Filter>res\common</Filter>
-    </None>
-    <None Include="res\common\duck.gpb">
-      <Filter>res\common</Filter>
-    </None>
-    <None Include="res\common\duck.material">
-      <Filter>res\common</Filter>
-    </None>
-    <None Include="res\common\gamepad.form">
-      <Filter>res\common</Filter>
-    </None>
-    <None Include="res\common\gamepad.theme">
-      <Filter>res\common</Filter>
-    </None>
-    <None Include="res\common\grid.material">
-      <Filter>res\common</Filter>
-    </None>
-    <None Include="res\common\inputs.form">
-      <Filter>res\common</Filter>
-    </None>
-    <None Include="res\common\light.form">
-      <Filter>res\common</Filter>
-    </None>
-    <None Include="res\common\light.material">
-      <Filter>res\common</Filter>
-    </None>
-    <None Include="res\common\lightBrickWall.gpb">
-      <Filter>res\common</Filter>
-    </None>
-    <None Include="res\common\physics.form">
-      <Filter>res\common</Filter>
-    </None>
-    <None Include="res\common\physics.gpb">
-      <Filter>res\common</Filter>
-    </None>
-    <None Include="res\common\physics.material">
-      <Filter>res\common</Filter>
-    </None>
-    <None Include="res\common\physics.physics">
-      <Filter>res\common</Filter>
-    </None>
-    <None Include="res\common\physics.scene">
-      <Filter>res\common</Filter>
-    </None>
-    <None Include="res\common\sample.gpb">
-      <Filter>res\common</Filter>
-    </None>
-    <None Include="res\common\sample.material">
-      <Filter>res\common</Filter>
-    </None>
-    <None Include="res\common\sample.scene">
-      <Filter>res\common</Filter>
-    </None>
-    <None Include="res\common\sphere.gpb">
-      <Filter>res\common</Filter>
-    </None>
-    <None Include="res\common\text.form">
-      <Filter>res\common</Filter>
-    </None>
-    <None Include="res\shaders\colored.frag">
-      <Filter>res\shaders</Filter>
-    </None>
-    <None Include="res\shaders\colored.vert">
-      <Filter>res\shaders</Filter>
-    </None>
-    <None Include="res\shaders\font.frag">
-      <Filter>res\shaders</Filter>
-    </None>
-    <None Include="res\shaders\font.vert">
-      <Filter>res\shaders</Filter>
-    </None>
-    <None Include="res\shaders\form.frag">
-      <Filter>res\shaders</Filter>
-    </None>
-    <None Include="res\shaders\form.vert">
-      <Filter>res\shaders</Filter>
-    </None>
-    <None Include="res\shaders\lighting.frag">
-      <Filter>res\shaders</Filter>
-    </None>
-    <None Include="res\shaders\lighting.vert">
-      <Filter>res\shaders</Filter>
-    </None>
-    <None Include="res\shaders\skinning.vert">
-      <Filter>res\shaders</Filter>
-    </None>
-    <None Include="res\shaders\skinning-none.vert">
-      <Filter>res\shaders</Filter>
-    </None>
-    <None Include="res\shaders\sprite.frag">
-      <Filter>res\shaders</Filter>
-    </None>
-    <None Include="res\shaders\sprite.vert">
-      <Filter>res\shaders</Filter>
-    </None>
-    <None Include="res\shaders\terrain.frag">
-      <Filter>res\shaders</Filter>
-    </None>
-    <None Include="res\shaders\terrain.vert">
-      <Filter>res\shaders</Filter>
-    </None>
-    <None Include="res\shaders\textured.frag">
-      <Filter>res\shaders</Filter>
-    </None>
-    <None Include="res\shaders\textured.vert">
-      <Filter>res\shaders</Filter>
-    </None>
-    <None Include="res\common\terrain\terrain.material">
-      <Filter>res\common\terrain</Filter>
-    </None>
-    <None Include="res\common\fonts\arial-distance.gpb">
-      <Filter>res\common\fonts</Filter>
-    </None>
-    <None Include="res\common\fonts\badaboom.gpb">
-      <Filter>res\common\fonts</Filter>
-    </None>
-    <None Include="res\common\fonts\custom.gpb">
-      <Filter>res\common\fonts</Filter>
-    </None>
-    <None Include="res\common\fonts\fishfingers.gpb">
-      <Filter>res\common\fonts</Filter>
-    </None>
-    <None Include="res\common\fonts\neuropol.gpb">
-      <Filter>res\common\fonts</Filter>
-    </None>
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include="src\MeshPrimitiveSample.h">
-      <Filter>src</Filter>
-    </ClInclude>
-    <ClInclude Include="src\CreateSceneSample.h">
-      <Filter>src</Filter>
-    </ClInclude>
-    <ClInclude Include="src\Audio3DSample.h">
-      <Filter>src</Filter>
-    </ClInclude>
-    <ClInclude Include="src\InputSample.h">
-      <Filter>src</Filter>
-    </ClInclude>
-    <ClInclude Include="src\LoadSceneSample.h">
-      <Filter>src</Filter>
-    </ClInclude>
-    <ClInclude Include="src\TextSample.h">
-      <Filter>src</Filter>
-    </ClInclude>
-    <ClInclude Include="src\TextureSample.h">
-      <Filter>src</Filter>
-    </ClInclude>
-    <ClInclude Include="src\SpriteBatchSample.h">
-      <Filter>src</Filter>
-    </ClInclude>
-    <ClInclude Include="src\Grid.h">
-      <Filter>src\common</Filter>
-    </ClInclude>
-    <ClInclude Include="src\FirstPersonCamera.h">
-      <Filter>src\common</Filter>
-    </ClInclude>
-    <ClInclude Include="src\SamplesGame.h">
-      <Filter>src\common</Filter>
-    </ClInclude>
-    <ClInclude Include="src\Sample.h">
-      <Filter>src\common</Filter>
-    </ClInclude>
-    <ClInclude Include="src\MeshBatchSample.h">
-      <Filter>src</Filter>
-    </ClInclude>
-    <ClInclude Include="src\TriangleSample.h">
-      <Filter>src</Filter>
-    </ClInclude>
-    <ClInclude Include="src\GestureSample.h">
-      <Filter>src</Filter>
-    </ClInclude>
-    <ClInclude Include="src\BillboardSample.h">
-      <Filter>src</Filter>
-    </ClInclude>
-    <ClInclude Include="src\FormsSample.h">
-      <Filter>src</Filter>
-    </ClInclude>
-    <ClInclude Include="src\LightSample.h">
-      <Filter>src</Filter>
-    </ClInclude>
-    <ClInclude Include="src\PostProcessSample.h">
-      <Filter>src</Filter>
-    </ClInclude>
-    <ClInclude Include="src\GamepadSample.h">
-      <Filter>src</Filter>
-    </ClInclude>
-    <ClInclude Include="src\PhysicsCollisionObjectSample.h">
-      <Filter>src</Filter>
-    </ClInclude>
-    <ClInclude Include="src\TerrainSample.h">
-      <Filter>src</Filter>
-    </ClInclude>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="src\MeshPrimitiveSample.cpp">
-      <Filter>src</Filter>
-    </ClCompile>
-    <ClCompile Include="src\CreateSceneSample.cpp">
-      <Filter>src</Filter>
-    </ClCompile>
-    <ClCompile Include="src\Audio3DSample.cpp">
-      <Filter>src</Filter>
-    </ClCompile>
-    <ClCompile Include="src\InputSample.cpp">
-      <Filter>src</Filter>
-    </ClCompile>
-    <ClCompile Include="src\LoadSceneSample.cpp">
-      <Filter>src</Filter>
-    </ClCompile>
-    <ClCompile Include="src\TextSample.cpp">
-      <Filter>src</Filter>
-    </ClCompile>
-    <ClCompile Include="src\TextureSample.cpp">
-      <Filter>src</Filter>
-    </ClCompile>
-    <ClCompile Include="src\SpriteBatchSample.cpp">
-      <Filter>src</Filter>
-    </ClCompile>
-    <ClCompile Include="src\Grid.cpp">
-      <Filter>src\common</Filter>
-    </ClCompile>
-    <ClCompile Include="src\FirstPersonCamera.cpp">
-      <Filter>src\common</Filter>
-    </ClCompile>
-    <ClCompile Include="src\Sample.cpp">
-      <Filter>src\common</Filter>
-    </ClCompile>
-    <ClCompile Include="src\SamplesGame.cpp">
-      <Filter>src\common</Filter>
-    </ClCompile>
-    <ClCompile Include="src\MeshBatchSample.cpp">
-      <Filter>src</Filter>
-    </ClCompile>
-    <ClCompile Include="src\TriangleSample.cpp">
-      <Filter>src</Filter>
-    </ClCompile>
-    <ClCompile Include="src\GestureSample.cpp">
-      <Filter>src</Filter>
-    </ClCompile>
-    <ClCompile Include="src\BillboardSample.cpp">
-      <Filter>src</Filter>
-    </ClCompile>
-    <ClCompile Include="src\FormsSample.cpp">
-      <Filter>src</Filter>
-    </ClCompile>
-    <ClCompile Include="src\LightSample.cpp">
-      <Filter>src</Filter>
-    </ClCompile>
-    <ClCompile Include="src\PostProcessSample.cpp">
-      <Filter>src</Filter>
-    </ClCompile>
-    <ClCompile Include="src\GamepadSample.cpp">
-      <Filter>src</Filter>
-    </ClCompile>
-    <ClCompile Include="src\PhysicsCollisionObjectSample.cpp">
-      <Filter>src</Filter>
-    </ClCompile>
-    <ClCompile Include="src\TerrainSample.cpp">
-      <Filter>src</Filter>
-    </ClCompile>
-  </ItemGroup>
-  <ItemGroup>
-    <Image Include="res\common\terrain\dirt.dds">
-      <Filter>res\common\terrain</Filter>
-    </Image>
-    <Image Include="res\common\terrain\grass.dds">
-      <Filter>res\common\terrain</Filter>
-    </Image>
-    <Image Include="res\common\terrain\normalmap.dds">
-      <Filter>res\common\terrain</Filter>
-    </Image>
-    <Image Include="res\common\terrain\rock.dds">
-      <Filter>res\common\terrain</Filter>
-    </Image>
-    <Image Include="res\common\terrain\sky.dds">
-      <Filter>res\common\terrain</Filter>
-    </Image>
-    <Image Include="res\logo_powered_white.png">
-      <Filter>res</Filter>
-    </Image>
-    <Image Include="res\png\brick.png">
-      <Filter>res\png</Filter>
-    </Image>
-    <Image Include="res\png\brickn.png">
-      <Filter>res\png</Filter>
-    </Image>
-    <Image Include="res\png\color-wheel.png">
-      <Filter>res\png</Filter>
-    </Image>
-    <Image Include="res\png\crate.png">
-      <Filter>res\png</Filter>
-    </Image>
-    <Image Include="res\png\default-theme.png">
-      <Filter>res\png</Filter>
-    </Image>
-    <Image Include="res\png\dirt.png">
-      <Filter>res\png</Filter>
-    </Image>
-    <Image Include="res\png\duck.png">
-      <Filter>res\png</Filter>
-    </Image>
-    <Image Include="res\png\gamepad.png">
-      <Filter>res\png</Filter>
-    </Image>
-    <Image Include="res\png\grass.png">
-      <Filter>res\png</Filter>
-    </Image>
-    <Image Include="res\png\light-directional.png">
-      <Filter>res\png</Filter>
-    </Image>
-    <Image Include="res\png\light-point.png">
-      <Filter>res\png</Filter>
-    </Image>
-    <Image Include="res\png\light-spot.png">
-      <Filter>res\png</Filter>
-    </Image>
-    <Image Include="res\png\logo.png">
-      <Filter>res\png</Filter>
-    </Image>
-  </ItemGroup>
-  <ItemGroup>
-    <Media Include="res\common\footsteps.wav">
-      <Filter>res\common</Filter>
-    </Media>
-  </ItemGroup>
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <Filter Include="src">
+    </Filter>
+    <Filter Include="src\common">
+      <UniqueIdentifier>{c35d9ec0-a966-49e8-af48-14cbcb2d6818}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="res">
+      <UniqueIdentifier>{b0da65f8-9ff6-4813-9af3-3bb222d54acf}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="res\common">
+      <UniqueIdentifier>{6cb7d9bf-0b2d-44df-a48d-d8150c67f38c}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="res\png">
+      <UniqueIdentifier>{6a436bab-00f5-4c87-9e53-b360dba474c2}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="res\common\forms">
+      <UniqueIdentifier>{a3201c29-9b57-40a3-839e-e5b8ad1fe53d}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="res\common\terrain">
+      <UniqueIdentifier>{7486d723-ca70-4cf7-a8fb-034679fad89f}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="res\common\postprocess">
+      <UniqueIdentifier>{97b23ce2-184f-46f4-a2fc-11aca4473fb3}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="res\shaders">
+      <UniqueIdentifier>{e1543678-e81b-48de-b753-3d5f000fd70b}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="res\common\fonts">
+      <UniqueIdentifier>{10e17594-e3ef-49d2-a2a4-fb874c32b5c7}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="game.config" />
+    <None Include="icon.png" />
+    <None Include="bar-descriptor.xml" />
+    <None Include="res\common\forms\formBasicControls.form">
+      <Filter>res\common\forms</Filter>
+    </None>
+    <None Include="res\common\forms\formFlowLayout.form">
+      <Filter>res\common\forms</Filter>
+    </None>
+    <None Include="res\common\forms\formScrolling.form">
+      <Filter>res\common\forms</Filter>
+    </None>
+    <None Include="res\common\forms\formSelect.form">
+      <Filter>res\common\forms</Filter>
+    </None>
+    <None Include="res\common\forms\formVerticalLayout.form">
+      <Filter>res\common\forms</Filter>
+    </None>
+    <None Include="res\common\forms\formZOrder.form">
+      <Filter>res\common\forms</Filter>
+    </None>
+    <None Include="res\common\postprocess\postprocess.material">
+      <Filter>res\common\postprocess</Filter>
+    </None>
+    <None Include="res\common\postprocess\postprocess.vert">
+      <Filter>res\common\postprocess</Filter>
+    </None>
+    <None Include="res\common\postprocess\postprocess_gaussianblur.frag">
+      <Filter>res\common\postprocess</Filter>
+    </None>
+    <None Include="res\common\postprocess\postprocess_grayscale.frag">
+      <Filter>res\common\postprocess</Filter>
+    </None>
+    <None Include="res\common\postprocess\postprocess_oldfilm.frag">
+      <Filter>res\common\postprocess</Filter>
+    </None>
+    <None Include="res\common\postprocess\postprocess_passthrough.frag">
+      <Filter>res\common\postprocess</Filter>
+    </None>
+    <None Include="res\common\postprocess\postprocess_pixelate.frag">
+      <Filter>res\common\postprocess</Filter>
+    </None>
+    <None Include="res\common\postprocess\postprocess_sepia.frag">
+      <Filter>res\common\postprocess</Filter>
+    </None>
+    <None Include="res\common\postprocess\postprocess_sobeledge.frag">
+      <Filter>res\common\postprocess</Filter>
+    </None>
+    <None Include="res\common\terrain\encode.bat">
+      <Filter>res\common\terrain</Filter>
+    </None>
+    <None Include="res\common\terrain\heightmap.r16">
+      <Filter>res\common\terrain</Filter>
+    </None>
+    <None Include="res\common\terrain\sample.scene">
+      <Filter>res\common\terrain</Filter>
+    </None>
+    <None Include="res\common\terrain\sample.terrain">
+      <Filter>res\common\terrain</Filter>
+    </None>
+    <None Include="res\common\terrain\shapes.material">
+      <Filter>res\common\terrain</Filter>
+    </None>
+    <None Include="res\common\terrain\sky.fbx">
+      <Filter>res\common\terrain</Filter>
+    </None>
+    <None Include="res\common\terrain\sky.gpb">
+      <Filter>res\common\terrain</Filter>
+    </None>
+    <None Include="res\common\terrain\sky.material">
+      <Filter>res\common\terrain</Filter>
+    </None>
+    <None Include="res\common\terrain\terrain.form">
+      <Filter>res\common\terrain</Filter>
+    </None>
+    <None Include="res\common\box.gpb">
+      <Filter>res\common</Filter>
+    </None>
+    <None Include="res\common\box.material">
+      <Filter>res\common</Filter>
+    </None>
+    <None Include="res\common\camera.lua">
+      <Filter>res\common</Filter>
+    </None>
+    <None Include="res\common\constraints.gpb">
+      <Filter>res\common</Filter>
+    </None>
+    <None Include="res\common\constraints.physics">
+      <Filter>res\common</Filter>
+    </None>
+    <None Include="res\common\constraints.scene">
+      <Filter>res\common</Filter>
+    </None>
+    <None Include="res\common\default.theme">
+      <Filter>res\common</Filter>
+    </None>
+    <None Include="res\common\duck.gpb">
+      <Filter>res\common</Filter>
+    </None>
+    <None Include="res\common\duck.material">
+      <Filter>res\common</Filter>
+    </None>
+    <None Include="res\common\gamepad.form">
+      <Filter>res\common</Filter>
+    </None>
+    <None Include="res\common\gamepad.theme">
+      <Filter>res\common</Filter>
+    </None>
+    <None Include="res\common\grid.material">
+      <Filter>res\common</Filter>
+    </None>
+    <None Include="res\common\inputs.form">
+      <Filter>res\common</Filter>
+    </None>
+    <None Include="res\common\light.form">
+      <Filter>res\common</Filter>
+    </None>
+    <None Include="res\common\light.material">
+      <Filter>res\common</Filter>
+    </None>
+    <None Include="res\common\lightBrickWall.gpb">
+      <Filter>res\common</Filter>
+    </None>
+    <None Include="res\common\physics.form">
+      <Filter>res\common</Filter>
+    </None>
+    <None Include="res\common\physics.gpb">
+      <Filter>res\common</Filter>
+    </None>
+    <None Include="res\common\physics.material">
+      <Filter>res\common</Filter>
+    </None>
+    <None Include="res\common\physics.physics">
+      <Filter>res\common</Filter>
+    </None>
+    <None Include="res\common\physics.scene">
+      <Filter>res\common</Filter>
+    </None>
+    <None Include="res\common\sample.gpb">
+      <Filter>res\common</Filter>
+    </None>
+    <None Include="res\common\sample.material">
+      <Filter>res\common</Filter>
+    </None>
+    <None Include="res\common\sample.scene">
+      <Filter>res\common</Filter>
+    </None>
+    <None Include="res\common\sphere.gpb">
+      <Filter>res\common</Filter>
+    </None>
+    <None Include="res\common\text.form">
+      <Filter>res\common</Filter>
+    </None>
+    <None Include="res\shaders\colored.frag">
+      <Filter>res\shaders</Filter>
+    </None>
+    <None Include="res\shaders\colored.vert">
+      <Filter>res\shaders</Filter>
+    </None>
+    <None Include="res\shaders\font.frag">
+      <Filter>res\shaders</Filter>
+    </None>
+    <None Include="res\shaders\font.vert">
+      <Filter>res\shaders</Filter>
+    </None>
+    <None Include="res\shaders\form.frag">
+      <Filter>res\shaders</Filter>
+    </None>
+    <None Include="res\shaders\form.vert">
+      <Filter>res\shaders</Filter>
+    </None>
+    <None Include="res\shaders\lighting.frag">
+      <Filter>res\shaders</Filter>
+    </None>
+    <None Include="res\shaders\lighting.vert">
+      <Filter>res\shaders</Filter>
+    </None>
+    <None Include="res\shaders\skinning.vert">
+      <Filter>res\shaders</Filter>
+    </None>
+    <None Include="res\shaders\skinning-none.vert">
+      <Filter>res\shaders</Filter>
+    </None>
+    <None Include="res\shaders\sprite.frag">
+      <Filter>res\shaders</Filter>
+    </None>
+    <None Include="res\shaders\sprite.vert">
+      <Filter>res\shaders</Filter>
+    </None>
+    <None Include="res\shaders\terrain.frag">
+      <Filter>res\shaders</Filter>
+    </None>
+    <None Include="res\shaders\terrain.vert">
+      <Filter>res\shaders</Filter>
+    </None>
+    <None Include="res\shaders\textured.frag">
+      <Filter>res\shaders</Filter>
+    </None>
+    <None Include="res\shaders\textured.vert">
+      <Filter>res\shaders</Filter>
+    </None>
+    <None Include="res\common\terrain\terrain.material">
+      <Filter>res\common\terrain</Filter>
+    </None>
+    <None Include="res\common\fonts\arial-distance.gpb">
+      <Filter>res\common\fonts</Filter>
+    </None>
+    <None Include="res\common\fonts\badaboom.gpb">
+      <Filter>res\common\fonts</Filter>
+    </None>
+    <None Include="res\common\fonts\custom.gpb">
+      <Filter>res\common\fonts</Filter>
+    </None>
+    <None Include="res\common\fonts\fishfingers.gpb">
+      <Filter>res\common\fonts</Filter>
+    </None>
+    <None Include="res\common\fonts\neuropol.gpb">
+      <Filter>res\common\fonts</Filter>
+    </None>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="src\MeshPrimitiveSample.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\CreateSceneSample.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\Audio3DSample.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\InputSample.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\LoadSceneSample.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\TextSample.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\TextureSample.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\SpriteBatchSample.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\Grid.h">
+      <Filter>src\common</Filter>
+    </ClInclude>
+    <ClInclude Include="src\FirstPersonCamera.h">
+      <Filter>src\common</Filter>
+    </ClInclude>
+    <ClInclude Include="src\SamplesGame.h">
+      <Filter>src\common</Filter>
+    </ClInclude>
+    <ClInclude Include="src\Sample.h">
+      <Filter>src\common</Filter>
+    </ClInclude>
+    <ClInclude Include="src\MeshBatchSample.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\TriangleSample.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\GestureSample.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\BillboardSample.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\FormsSample.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\LightSample.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\PostProcessSample.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\GamepadSample.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\PhysicsCollisionObjectSample.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\TerrainSample.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\WaterSample.h">
+      <Filter>src</Filter>
+    </ClInclude>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="src\MeshPrimitiveSample.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\CreateSceneSample.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\Audio3DSample.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\InputSample.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\LoadSceneSample.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\TextSample.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\TextureSample.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\SpriteBatchSample.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\Grid.cpp">
+      <Filter>src\common</Filter>
+    </ClCompile>
+    <ClCompile Include="src\FirstPersonCamera.cpp">
+      <Filter>src\common</Filter>
+    </ClCompile>
+    <ClCompile Include="src\Sample.cpp">
+      <Filter>src\common</Filter>
+    </ClCompile>
+    <ClCompile Include="src\SamplesGame.cpp">
+      <Filter>src\common</Filter>
+    </ClCompile>
+    <ClCompile Include="src\MeshBatchSample.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\TriangleSample.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\GestureSample.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\BillboardSample.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\FormsSample.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\LightSample.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\PostProcessSample.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\GamepadSample.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\PhysicsCollisionObjectSample.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\TerrainSample.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\WaterSample.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <Image Include="res\common\terrain\dirt.dds">
+      <Filter>res\common\terrain</Filter>
+    </Image>
+    <Image Include="res\common\terrain\grass.dds">
+      <Filter>res\common\terrain</Filter>
+    </Image>
+    <Image Include="res\common\terrain\normalmap.dds">
+      <Filter>res\common\terrain</Filter>
+    </Image>
+    <Image Include="res\common\terrain\rock.dds">
+      <Filter>res\common\terrain</Filter>
+    </Image>
+    <Image Include="res\common\terrain\sky.dds">
+      <Filter>res\common\terrain</Filter>
+    </Image>
+    <Image Include="res\logo_powered_white.png">
+      <Filter>res</Filter>
+    </Image>
+    <Image Include="res\png\brick.png">
+      <Filter>res\png</Filter>
+    </Image>
+    <Image Include="res\png\brickn.png">
+      <Filter>res\png</Filter>
+    </Image>
+    <Image Include="res\png\color-wheel.png">
+      <Filter>res\png</Filter>
+    </Image>
+    <Image Include="res\png\crate.png">
+      <Filter>res\png</Filter>
+    </Image>
+    <Image Include="res\png\default-theme.png">
+      <Filter>res\png</Filter>
+    </Image>
+    <Image Include="res\png\dirt.png">
+      <Filter>res\png</Filter>
+    </Image>
+    <Image Include="res\png\duck.png">
+      <Filter>res\png</Filter>
+    </Image>
+    <Image Include="res\png\gamepad.png">
+      <Filter>res\png</Filter>
+    </Image>
+    <Image Include="res\png\grass.png">
+      <Filter>res\png</Filter>
+    </Image>
+    <Image Include="res\png\light-directional.png">
+      <Filter>res\png</Filter>
+    </Image>
+    <Image Include="res\png\light-point.png">
+      <Filter>res\png</Filter>
+    </Image>
+    <Image Include="res\png\light-spot.png">
+      <Filter>res\png</Filter>
+    </Image>
+    <Image Include="res\png\logo.png">
+      <Filter>res\png</Filter>
+    </Image>
+  </ItemGroup>
+  <ItemGroup>
+    <Media Include="res\common\footsteps.wav">
+      <Filter>res\common</Filter>
+    </Media>
+  </ItemGroup>
 </Project>

+ 361 - 0
samples/browser/src/WaterSample.cpp

@@ -0,0 +1,361 @@
+#include "WaterSample.h"
+#include "SamplesGame.h"
+
+#if defined(ADD_SAMPLE)
+ADD_SAMPLE("Graphics", "Water", WaterSample, 14);
+#endif
+
+//camera movement consts
+static const float MOUSE_SPEED = 0.125f;
+static const float MASS = 1.8f;
+static const float FRICTION = 0.9f;
+static const float SPEED = 5.5f;
+//
+static const unsigned BUFFER_SIZE = 512u;
+static const float WATER_OFFSET = 0.55f;
+
+WaterSample::WaterSample()
+    : _font(NULL), _scene(NULL), _cameraNode(NULL),
+    _reflectCameraNode(NULL), _inputMask(0u), _prevX(0),
+     _prevY(0), _waterHeight(0.f), _refractBuffer(NULL),
+     _refractBatch(NULL), _reflectBuffer(NULL), _reflectBatch(NULL),
+     _showBuffers(true), _gamepad(NULL)
+{
+
+}
+
+void WaterSample::initialize()
+{
+    // Create the font for drawing the framerate.
+    _font = Font::create("res/ui/arial.gpb");
+
+    //load the scene file
+    _scene = Scene::load("res/common/water/watersample.scene");
+    _waterHeight = _scene->findNode("Water")->getTranslationY();
+
+    //----set up a first person style camera----//
+    const Vector3 camStartPosition(0.f, 10.f, -30.f);
+
+    _cameraNode = Node::create("cameraNode");
+    _cameraNode->setTranslation(camStartPosition);
+
+    Node* camPitchNode = Node::create();
+    Matrix m;
+    Matrix::createLookAt(_cameraNode->getTranslation(), Vector3::zero(), Vector3::unitY(), &m);
+    camPitchNode->rotate(m);
+    _cameraNode->addChild(camPitchNode);
+    _scene->addNode(_cameraNode);
+
+    Camera* camera = Camera::createPerspective(45.f, Game::getInstance()->getAspectRatio(), 0.1f, 150.f);
+    camPitchNode->setCamera(camera);
+    _scene->setActiveCamera(camera);
+    SAFE_RELEASE(camera);
+    SAFE_RELEASE(camPitchNode);
+
+    //add a second camera do draw the reflections
+    _reflectCameraNode = Node::create("reflectCamNode");
+    _reflectCameraNode->setTranslation(camStartPosition.x, -camStartPosition.y, camStartPosition.z);
+
+    camPitchNode = Node::create();
+    Matrix::createLookAt(_reflectCameraNode->getTranslation(), Vector3::zero(), Vector3::unitY(), &m);
+    camPitchNode->rotate(m);
+    _reflectCameraNode->addChild(camPitchNode);
+
+    camera = Camera::createPerspective(45.f, Game::getInstance()->getAspectRatio(), 0.1f, 150.f);
+    camPitchNode->setCamera(camera);
+    SAFE_RELEASE(camera);
+    SAFE_RELEASE(camPitchNode);
+    //------------------------------------------//
+
+    //---render buffer and preview for refraction---//
+    _refractBuffer = FrameBuffer::create("refractBuffer", BUFFER_SIZE, BUFFER_SIZE);
+    DepthStencilTarget* refractDepthTarget = DepthStencilTarget::create("refractDepth", DepthStencilTarget::DEPTH, BUFFER_SIZE, BUFFER_SIZE);
+    _refractBuffer->setDepthStencilTarget(refractDepthTarget);
+    SAFE_RELEASE(refractDepthTarget);
+    _refractBatch = SpriteBatch::create(_refractBuffer->getRenderTarget()->getTexture());
+    //----------------------------------------------//
+
+    //---render buffer and preview for reflection---//
+    _reflectBuffer = FrameBuffer::create("reflectBuffer", BUFFER_SIZE, BUFFER_SIZE);
+    DepthStencilTarget* reflectDepthTarget = DepthStencilTarget::create("reflectDepth", DepthStencilTarget::DEPTH, BUFFER_SIZE, BUFFER_SIZE);
+    _reflectBuffer->setDepthStencilTarget(reflectDepthTarget);
+    SAFE_RELEASE(reflectDepthTarget);
+    _reflectBatch = SpriteBatch::create(_reflectBuffer->getRenderTarget()->getTexture());
+    //----------------------------------------------//
+
+    //----add a node to provide light direction-----//
+    Node* lightNode = Node::create("lightNode");
+    lightNode->rotateX(-MATH_DEG_TO_RAD(90));
+    _scene->addNode(lightNode);
+
+    //---bind uniforms to material properties---//
+    Material* groundMaterial = _scene->findNode("Ground")->getModel()->getMaterial();
+    groundMaterial->getParameter("u_clipPlane")->bindValue(this, &WaterSample::getClipPlane);
+    groundMaterial->getParameter("u_directionalLightDirection[0]")->bindValue(lightNode, &Node::getForwardVectorView);
+    auto waterMaterial = _scene->findNode("Water")->getModel()->getMaterial();
+    auto refractSampler = Texture::Sampler::create(_refractBuffer->getRenderTarget()->getTexture());
+    waterMaterial->getParameter("u_refractionTexture")->setSampler(refractSampler);
+    SAFE_RELEASE(refractSampler);
+    auto reflectSampler = Texture::Sampler::create(_reflectBuffer->getRenderTarget()->getTexture());
+    waterMaterial->getParameter("u_reflectionTexture")->setSampler(reflectSampler);
+    SAFE_RELEASE(reflectSampler);
+    waterMaterial->getParameter("u_worldViewProjectionReflectionMatrix")->bindValue(this, &WaterSample::getReflectionMatrix);
+    waterMaterial->getParameter("u_time")->bindValue(this, &WaterSample::getTime);
+    //------------------------------------------//
+
+    SAFE_RELEASE(lightNode);
+
+    setMouseCaptured(true);
+
+    setMultiTouch(true);
+    _gamepad = getGamepad(0);
+    // This is needed because the virtual gamepad is shared between all samples.
+    // SamplesGame always ensures the virtual gamepad is disabled when a sample is exited.
+    if (_gamepad && _gamepad->isVirtual())
+        _gamepad->getForm()->setEnabled(true);
+
+}
+
+void WaterSample::finalize()
+{
+    setMouseCaptured(false);
+
+    //relese ref counted members
+    SAFE_DELETE(_reflectBatch);
+    SAFE_RELEASE(_reflectBuffer);
+    SAFE_DELETE(_refractBatch);
+    SAFE_RELEASE(_refractBuffer);
+    SAFE_RELEASE(_reflectCameraNode);
+    SAFE_RELEASE(_cameraNode);
+    SAFE_RELEASE(_scene);
+    SAFE_RELEASE(_font);
+}
+
+void WaterSample::update(float elapsedTime)
+{
+    //check controller state
+    Vector2 axis;
+    const float minVal = 0.1f;
+    if (_gamepad && _gamepad->getJoystickCount())
+    {
+        _gamepad->getJoystickValues(0, &axis);
+    }
+    
+    //move the camera by applying a force
+    Vector3 force;
+    if (_inputMask & Button::Forward || axis.y > minVal)
+        force += _cameraNode->getFirstChild()->getForwardVectorWorld();
+    if (_inputMask & Button::Back || axis.y < -minVal)
+        force -= _cameraNode->getFirstChild()->getForwardVectorWorld();
+    if (_inputMask & Button::Left || axis.x < -minVal)
+        force += _cameraNode->getRightVectorWorld();
+    if (_inputMask & Button::Right || axis.y > minVal)
+        force -= _cameraNode->getRightVectorWorld();
+    if (force.lengthSquared() > 1.f) force.normalize();
+
+    _cameraAcceleration += force / MASS;
+    _cameraAcceleration *= FRICTION;
+    if (_cameraAcceleration.lengthSquared() < 0.01f)
+        _cameraAcceleration = Vector3::zero();
+    _cameraNode->translate(_cameraAcceleration * SPEED * (elapsedTime / 1000.f));
+    
+    //make sure the reflection camera follows
+    Vector3 position = _cameraNode->getTranslation();
+    position.y = -position.y + _waterHeight * 2.f;
+    _reflectCameraNode->setTranslation(position);
+    //------------------------------------- 
+}
+
+void WaterSample::render(float elapsedTime)
+{
+    const Vector4 clearColour(0.84f, 0.89f, 1.f, 1.f);
+    
+    //update the refract buffer
+    FrameBuffer* defaultBuffer = _refractBuffer->bind();
+    Rectangle defaultViewport = getViewport();
+    setViewport(Rectangle(BUFFER_SIZE, BUFFER_SIZE));
+
+    _clipPlane.y = -1.f;
+    _clipPlane.w = _waterHeight + WATER_OFFSET;
+    clear(CLEAR_COLOR_DEPTH, clearColour, 1.0f, 0);
+    _scene->visit(this, &WaterSample::drawScene, false);
+
+    //switch plane direction and camera, and update reflection buffer
+    _reflectBuffer->bind();
+    _clipPlane.y = 1.f;
+    _clipPlane.w = -_waterHeight + WATER_OFFSET;
+
+    Camera* defaultCam = _scene->getActiveCamera();
+    _scene->setActiveCamera(_reflectCameraNode->getFirstChild()->getCamera());
+    //store the mvp matrix here as it is only valid when reflect camera is active
+    m_worldViewProjectionReflection = _scene->findNode("Water")->getWorldViewProjectionMatrix();
+    clear(CLEAR_COLOR_DEPTH, clearColour, 1.0f, 0);
+    _scene->visit(this, &WaterSample::drawScene, false);
+
+    //draw the final scene
+    defaultBuffer->bind();
+    setViewport(defaultViewport);
+    _clipPlane = Vector4::zero();
+    _scene->setActiveCamera(defaultCam);
+    clear(CLEAR_COLOR_DEPTH, clearColour, 1.0f, 0);
+    _scene->visit(this, &WaterSample::drawScene, true);
+
+    //draw preview if enabled
+    if (_showBuffers)
+    {
+        _refractBatch->start();
+        _refractBatch->draw(Vector3(0.f, 4.f, 0.f), Rectangle(BUFFER_SIZE, BUFFER_SIZE), Vector2(426.f, 240.f));
+        _refractBatch->finish();
+        _reflectBatch->start();
+        _reflectBatch->draw(Vector3(430.f, 4.f, 0.f), Rectangle(BUFFER_SIZE, BUFFER_SIZE), Vector2(426.f, 240.f));
+        _reflectBatch->finish();
+    }
+
+    // draw the gamepad
+    _gamepad->draw();
+
+    drawFrameRate(_font, Vector4(0, 0.5f, 1, 1), 5, 1, getFrameRate());
+}
+
+void WaterSample::touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex)
+{
+    switch (evt)
+    {
+    case Touch::TOUCH_PRESS:
+        if (x < 75 && y < 50)
+        {
+            // Toggle buffer preview if the user touches the top left corner
+            _showBuffers = !_showBuffers;
+        }
+        _prevX = x;
+        _prevY = y;
+        break;
+    case Touch::TOUCH_RELEASE:
+        _prevX = x;
+        _prevY = y;
+        break;
+    case Touch::TOUCH_MOVE:
+    {
+        int deltaX = x - _prevX;
+        int deltaY = y - _prevY;
+        _prevX = x;
+        _prevY = y;
+        
+        float xMovement = MATH_DEG_TO_RAD(deltaX * 0.25f);
+        float yMovement = MATH_DEG_TO_RAD(-deltaY * 0.25f);
+        _cameraNode->rotateY(-xMovement);
+        _cameraNode->getFirstChild()->rotateX(yMovement);
+        _reflectCameraNode->rotateY(-xMovement);
+        _reflectCameraNode->getFirstChild()->rotateX(-yMovement);
+    }
+        break;
+    };
+}
+
+void WaterSample::keyEvent(Keyboard::KeyEvent evt, int key)
+{
+    if (evt == Keyboard::KEY_PRESS)
+    {
+        switch (key)
+        {
+        case Keyboard::KEY_SPACE:
+            _showBuffers = !_showBuffers;
+            break;
+        case Keyboard::KEY_W:
+        case Keyboard::KEY_UP_ARROW:
+            _inputMask |= Button::Forward;
+            break;
+        case Keyboard::KEY_S:
+        case Keyboard::KEY_DOWN_ARROW:
+            _inputMask |= Button::Back;
+            break;
+        case Keyboard::KEY_A:
+        case Keyboard::KEY_LEFT_ARROW:
+            _inputMask |= Button::Left;
+            break;
+        case Keyboard::KEY_D:
+        case Keyboard::KEY_RIGHT_ARROW:
+            _inputMask |= Button::Right;
+            break;
+        }
+    }
+    else if (evt == Keyboard::KEY_RELEASE)
+    {
+        switch (key)
+        {
+        case Keyboard::KEY_W:
+        case Keyboard::KEY_UP_ARROW:
+            _inputMask &= ~Button::Forward;
+            break;
+        case Keyboard::KEY_S:
+        case Keyboard::KEY_DOWN_ARROW:
+            _inputMask &= ~Button::Back;
+            break;
+        case Keyboard::KEY_A:
+        case Keyboard::KEY_LEFT_ARROW:
+            _inputMask &= ~Button::Left;
+            break;
+        case Keyboard::KEY_D:
+        case Keyboard::KEY_RIGHT_ARROW:
+            _inputMask &= ~Button::Right;
+            break;
+        }
+    }
+}
+
+bool WaterSample::mouseEvent(Mouse::MouseEvent evt, int x, int y, int wheelDelta)
+{
+    switch (evt)
+    {
+    case Mouse::MOUSE_MOVE:
+    {
+        float xMovement = MATH_DEG_TO_RAD(-x * MOUSE_SPEED);
+        float yMovement = MATH_DEG_TO_RAD(-y * MOUSE_SPEED);
+        _cameraNode->rotateY(xMovement);
+        _cameraNode->getFirstChild()->rotateX(yMovement);
+        _reflectCameraNode->rotateY(xMovement);
+        _reflectCameraNode->getFirstChild()->rotateX(-yMovement);
+    }
+        return true;
+    case Mouse::MOUSE_PRESS_LEFT_BUTTON:
+        _inputMask |= Button::Forward;
+        return true;
+    case Mouse::MOUSE_RELEASE_LEFT_BUTTON:
+        _inputMask &= ~Button::Forward;
+        return true;
+    case Mouse::MOUSE_PRESS_RIGHT_BUTTON:
+        _inputMask |= Button::Back;
+        return true;
+    case Mouse::MOUSE_RELEASE_RIGHT_BUTTON:
+        _inputMask &= ~Button::Back;
+        return true;
+    default: return false;
+    }
+    return false;
+}
+
+void WaterSample::gamepadEvent(Gamepad::GamepadEvent evt, Gamepad* gamepad)
+{
+    switch (evt)
+    {
+    case Gamepad::CONNECTED_EVENT:
+    case Gamepad::DISCONNECTED_EVENT:
+        _gamepad = getGamepad(0);
+        // This is needed because the virtual gamepad is shared between all samples.
+        // SamplesGame always ensures the virtual gamepad is disabled when a sample is exited.
+        if (_gamepad && _gamepad->isVirtual())
+            _gamepad->getForm()->setEnabled(true);
+        break;
+    }
+}
+
+bool WaterSample::drawScene(Node* node, bool drawWater)
+{
+    std::string id = node->getId();
+    if (!drawWater && id == "Water") return true;
+    
+    Model* model = node->getModel();
+    if (model)
+        model->draw();
+    return true;
+}

+ 84 - 0
samples/browser/src/WaterSample.h

@@ -0,0 +1,84 @@
+#ifndef WATERSAMPLE_H_
+#define WATERSAMPLE_H_
+
+#include "gameplay.h"
+#include "Sample.h"
+
+
+using namespace gameplay;
+
+/**
+* Sample creating a water effect.
+*/
+class WaterSample : public Sample
+{
+public:
+
+    WaterSample();
+
+    void touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex);
+    
+    void keyEvent(Keyboard::KeyEvent evt, int key);
+
+    bool mouseEvent(Mouse::MouseEvent evt, int x, int y, int wheelDelta);
+
+    void gamepadEvent(Gamepad::GamepadEvent evt, Gamepad* gamepad);
+
+protected:
+
+    void initialize();
+
+    void finalize();
+
+    void update(float elapsedTime);
+
+    void render(float elapsedTime);
+
+private:
+    enum Button
+    {
+        Forward     = (1 << 0),
+        Back        = (1 << 1),
+        Left        = (1 << 2),
+        Right       = (1 << 3)
+    };
+
+    Font* _font;
+    Scene* _scene;
+    Node* _cameraNode;
+    Node* _reflectCameraNode;
+
+    Vector3 _cameraAcceleration;
+    float _waterHeight;
+
+    unsigned _inputMask;
+    int _prevX, _prevY;
+
+    FrameBuffer* _refractBuffer;
+    SpriteBatch* _refractBatch;
+    FrameBuffer* _reflectBuffer;
+    SpriteBatch* _reflectBatch;
+
+    bool _showBuffers;
+
+    Vector4 _clipPlane;
+    const Vector4& getClipPlane() const
+    {
+        return _clipPlane;
+    }
+    Matrix m_worldViewProjectionReflection;
+    const Matrix& getReflectionMatrix() const
+    {
+        return m_worldViewProjectionReflection;
+    }
+
+    float getTime() const
+    {
+        return Game::getGameTime() * 0.0001;
+    }
+
+    Gamepad* _gamepad;
+    bool drawScene(Node* node, bool drawWater);
+};
+
+#endif