/*********************************************************************NVMH3****
Copyright NVIDIA Corporation 2003
TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THIS SOFTWARE IS PROVIDED
*AS IS* AND NVIDIA AND ITS SUPPLIERS DISCLAIM ALL WARRANTIES, EITHER EXPRESS
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE.  IN NO EVENT SHALL NVIDIA OR ITS SUPPLIERS
BE LIABLE FOR ANY SPECIAL, INCIDENTAL, INDIRECT, OR CONSEQUENTIAL DAMAGES
WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS,
BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR ANY OTHER PECUNIARY LOSS)
ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF NVIDIA HAS
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.


Comments:
	Simple ocean shader with animated bump map and geometric waves
	Based partly on "Effective Water Simulation From Physical Models", GPU Gems

11 Aug 05: converted from HLSL to GLSL by Jeff Doyle (nfz) to work in Ogre
15 Jun 25: modified to work with OgreUnifiedShader.h

******************************************************************************/
OGRE_NATIVE_GLSL_VERSION_DIRECTIVE
#include <OgreUnifiedShader.h>

#if NEW_WATER_SHADER
OGRE_UNIFORMS(
uniform mat4 projectionMatrix;
uniform mat4 viewMatrix;
uniform mat4 modelMatrix;
)
const float tiling = 0.012;
MAIN_PARAMETERS
IN(vec4 position, POSITION)
OUT(vec4 clipSpace, TEXCOORD0)
OUT(vec2 textureCoords, TEXCOORD1)
MAIN_DECLARATION
{
	clipSpace = projectionMatrix * viewMatrix * modelMatrix * vec4(position.xyz, 1.0);
	vec4 worldPos = modelMatrix * vec4(position.xyz, 1.0);
	gl_Position = clipSpace;
	textureCoords = vec2(worldPos.x / 2.0 + 0.5, worldPos.z / 2.0 + 0.5) * tiling;
}

#else
OGRE_UNIFORMS(
uniform vec3 eyePosition;
uniform float BumpScale;
uniform vec2 textureScale;
uniform vec2 bumpSpeed;
uniform highp float time;
uniform float waveFreq;
uniform float waveAmp;
uniform vec4 cameraPositionOS;
uniform mat4 world;
uniform mat4 viewProj;
uniform mat4 worldView;
uniform mat4 worldViewProj;
uniform mat4 textureProjMatrix;
uniform mat3 normalMatrix;
uniform vec3 lightDirection;
uniform float scale;  // the amount to scale the noise texture by
uniform float scroll; // the amount by which to scroll the noise
uniform float noise;  // the noise perturb as a factor of the time
)
#line 41
//vec4 wave_a = vec4(1.0, 1.0, 0.35, 3.0); 	// xy = Direction, z = Steepness, w = Length
f32vec4 wave_a = vec4(1.0, 1.0, 0.08, 35.3); 	// xy = Direction, z = Steepness, w = Length
f32vec4 wave_b = vec4(1.0, 0.6, 0.02, 21.55);	// xy = Direction, z = Steepness, w = Length
f32vec4 wave_c = vec4(1.0, 1.41, 0.01, 0.8); 	// xy = Direction, z = Steepness, w = Length
f32vec4 wave_d = vec4(-1.2, 1.0, 0.01, 0.1); 	// xy = Direction, z = Steepness, w = Length

f32vec4 wave(f32vec4 parameter, f32vec2 position, float32_t t, inout f32vec3 tangent, inout f32vec3 binormal)
{
#line 51
	f32vec2 dir = normalize(parameter.xy);
	float32_t wave_steepness = parameter.z;
	float32_t wave_length = parameter.w;
	float32_t freq = 2.0 * 3.14159265359 / wave_length;
	float32_t phase = sqrt(9.8 / freq);
	float32_t f = freq * (dot(dir, position) - phase * t);
	float32_t a = wave_steepness / freq;
	tangent += normalize(
		vec3(1.0 - dir.x * dir.x * (wave_steepness * sin(f)), dir.x * (wave_steepness * cos(f)), -dir.x * dir.y * (wave_steepness * sin(f)))
	);
	binormal += normalize(
		vec3( -dir.x * dir.y * (wave_steepness * sin(f)), dir.y * (wave_steepness * cos(f)), 1.0-dir.y * dir.y * (wave_steepness * sin(f)))
	);
	
	f32vec4 result = vec4(dir.x * a * cos(f), a * sin(f) * 0.25, dir.y * (a * cos(f)), 0.0);
	return result;
}
vec4 wave2(vec4 parameter, vec2 position, float t, inout vec3 tangent, inout vec3 binormal)
{
	vec2 dir = normalize(parameter.xy);
	float wave_steepness = parameter.z;
	float wave_length = parameter.w;
	float freq = 2.0 * 3.14159265359 / wave_length;
	float phase = sqrt(9.8 / freq);
	float f = freq * (dot(dir, position) - phase * t);
	float a = wave_steepness / freq;
	float m = freq * (position.x - phase * t);
	float n = freq * (position.y - phase * t);
	tangent += normalize(
		vec3(1.0-sin(m), cos(m), -sin(m))
	);
	binormal += normalize(
		vec3( -sin(n), cos(n), 1.0-sin(n))
	);
	return vec4(dir.x * a * cos(f), a * sin(f) * 0.25, dir.y * (a * cos(f)), 0.0);
}
MAIN_PARAMETERS
IN(vec4 vertex, POSITION)
IN(vec3 normal, NORMAL)
IN(vec3 tangent, TANGENT)
IN(vec4 uv0, TEXCOORD0)
OUT(f32vec3 positionWS, TEXCOORD0)
OUT(f32vec3 vnormal, TEXCOORD1)
OUT(f32vec3 viewDirection, TEXCOORD2)
OUT(f32vec3 viewDirectionTS, TEXCOORD3)
OUT(f32vec3 olightDirection, TEXCOORD4)
// OUT(f32vec3 vbinormal, TEXCOORD2)
// OUT(f32vec3 vtangent, TEXCOORD3)
// OUT(float vertex_height, TEXCOORD4)
OUT(f32vec3 lightDirectionTS, TEXCOORD5)
OUT(f32vec2 bumpCoord0, TEXCOORD6)
MAIN_DECLARATION
{
	float textureScale = 0.6;
	float bumpSpeed = 0.8;
	f32vec4 position = vec4(mul(world, vertex).xyz, 1.0);
	f32vec3 vertex_position = position.xyz;
	f32vec3 tang = tangent;
	f32vec3 bin = cross(tangent, normal);
	position += wave(wave_a, vertex_position.xz, time, tang, bin);
	position += wave(wave_b, vertex_position.xz, time, tang, bin);
	position += wave(wave_c, vertex_position.xz, time, tang, bin);
	position += wave(wave_d, vertex_position.xz, time, tang, bin);
	// vtangent = tang;
	// vbinormal = bin;
	// vertex_position = position.xyz;
	// vnormal = normalize(mul(mat3(world), cross(vbinormal, vtangent)));
	vnormal = normalize(cross(bin, tang));
	mat3 TBN = mtxFromRows(tang, bin, vnormal);
	// vnormal = normalize(vec3(0.0, 1.0, 0.0));
	
	// gl_Position = mul(worldViewProj, vertex);
	viewDirection = vertex.xyz - cameraPositionOS.xyz;
	viewDirectionTS = mul(TBN, viewDirection);
	olightDirection = lightDirection;
	lightDirectionTS = mul(TBN, lightDirection);
	gl_Position = mul(viewProj, position);
	positionWS = mul(world, vertex).xyz;
	bumpCoord0.xy = uv0.xy * textureScale + time * bumpSpeed;
}
#endif

