summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Maskell <[email protected]>2016-05-23 13:25:08 +0200
committerJason Maskell <[email protected]>2016-05-23 13:25:08 +0200
commit9eb5141c98951c36ed8561a0b0571c511a96ef95 (patch)
treef536a91154df6b1b2bdaa3709a8bdd172c17769c
parentMoved media to a more central location. (diff)
downloadwaveworks_archive-9eb5141c98951c36ed8561a0b0571c511a96ef95.tar.xz
waveworks_archive-9eb5141c98951c36ed8561a0b0571c511a96ef95.zip
Added OpenGL sample - compiles and runs but doesn't work.
-rw-r--r--CMakeLists.txt3
-rw-r--r--cmake/FindAntTweakBar.cmake40
-rw-r--r--compiler/cmake/sample_d3d11.cmake6
-rw-r--r--compiler/cmake/sample_opengl.cmake140
-rw-r--r--sample/opengl/math_code.cpp488
-rw-r--r--sample/opengl/math_code.h49
-rw-r--r--sample/opengl/ocean_surface.cppbin0 -> 64730 bytes
-rw-r--r--sample/opengl/ocean_surface.h345
-rw-r--r--sample/opengl/sample_opengl.cpp850
-rw-r--r--sample/opengl/water.glsl170
10 files changed, 2088 insertions, 3 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 38b86a1..71f4bce 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -11,6 +11,8 @@ LIST(APPEND CMAKE_MODULE_PATH ${GW_DEPS_ROOT}CMakeModules)
MESSAGE(${CMAKE_MODULE_PATH})
+
+
# TODO: Fail if we didn't find deps
IF(CMAKE_CONFIGURATION_TYPES)
@@ -126,3 +128,4 @@ SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE ${FINAL_OUTPUT_DIR})
INCLUDE(compiler/cmake/NvWaveWorks.cmake)
INCLUDE(compiler/cmake/test_d3d11.cmake)
INCLUDE(compiler/cmake/sample_d3d11.cmake)
+INCLUDE(compiler/cmake/sample_opengl.cmake)
diff --git a/cmake/FindAntTweakBar.cmake b/cmake/FindAntTweakBar.cmake
new file mode 100644
index 0000000..a25e9a0
--- /dev/null
+++ b/cmake/FindAntTweakBar.cmake
@@ -0,0 +1,40 @@
+# Find AntTweakBar
+
+include(FindPackageHandleStandardArgs)
+
+if (CMAKE_CL_64)
+ set(ATBARCH "64")
+else()
+ set(ATBARCH "")
+endif()
+
+find_path(ATB_PATH AntTweakBar.h
+ HINTS ${GW_DEPS_ROOT}/AntTweakBar
+ )
+
+MESSAGE("ATB SDK ${ATB_PATH}")
+
+find_library(ATB_LIBRARY_RELEASE
+ NAMES AntTweakBar${ATBARCH}
+ PATHS ${ATB_PATH})
+
+# find_library(ATB_LIBRARY_DEBUG
+ # NAMES AntTweakBar${ATBARCH}
+ # PATHS ${ATB_PATH}/debug)
+
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(ATB
+ DEFAULT_MSG
+ ATB_LIBRARY_RELEASE
+ ATB_PATH)
+
+if(ATB_FOUND)
+ mark_as_advanced(ATB_PATH ATB_LIBRARY_RELEASE ATB_LIBRARY_DEBUG)
+ set(ATB_INCLUDE_DIRS
+ ${ATB_PATH}
+ CACHE STRING "")
+
+ set(ATB_LIBRARIES
+ optimized ${ATB_LIBRARY_RELEASE}
+ debug ${ATB_LIBRARY_RELEASE}
+ CACHE STRING "")
+endif()
diff --git a/compiler/cmake/sample_d3d11.cmake b/compiler/cmake/sample_d3d11.cmake
index 5b6b4e0..28f9895 100644
--- a/compiler/cmake/sample_d3d11.cmake
+++ b/compiler/cmake/sample_d3d11.cmake
@@ -1,5 +1,5 @@
#
-# Build test_d3d11
+# Build sample_d3d11
#
SET(GW_DEPS_ROOT $ENV{GW_DEPS_ROOT})
@@ -26,9 +26,9 @@ IF(TARGET_BUILD_PLATFORM STREQUAL "Windows")
# Use generator expressions to set config specific preprocessor definitions
SET(WW_COMPILE_DEFS
# Common to all configurations
- _LIB;NVWAVEWORKS_LIB_DLL_EXPORTS;WIN32;
+ WIN32;_WINDOWS
- $<$<CONFIG:debug>:PROFILE;_DEV;>
+ $<$<CONFIG:debug>:PROFILE;>
$<$<CONFIG:release>:NDEBUG;>
)
diff --git a/compiler/cmake/sample_opengl.cmake b/compiler/cmake/sample_opengl.cmake
new file mode 100644
index 0000000..ce71e04
--- /dev/null
+++ b/compiler/cmake/sample_opengl.cmake
@@ -0,0 +1,140 @@
+#
+# Build sample_opengl
+#
+
+SET(GW_DEPS_ROOT $ENV{GW_DEPS_ROOT})
+
+FIND_PACKAGE(AntTweakBar REQUIRED)
+
+SET(SAMP_SOURCE_DIR ${PROJECT_SOURCE_DIR}/sample/opengl)
+SET(TL_INCLUDE_DIR ${PROJECT_SOURCE_DIR}/include)
+
+IF(TARGET_BUILD_PLATFORM STREQUAL "Windows")
+
+ FIND_PACKAGE(DirectX REQUIRED)
+
+ SET(WW_PLATFORM_INCLUDES
+ )
+
+ SET(WW_PLATFORM_SRC_FILES
+ )
+
+
+ # Use generator expressions to set config specific preprocessor definitions
+ SET(WW_COMPILE_DEFS
+ # Common to all configurations
+ WIN32;_WINDOWS;_CONSOLE;
+
+ $<$<CONFIG:debug>:PROFILE;>
+ $<$<CONFIG:release>:NDEBUG;>
+ )
+
+ SET(WW_LIBTYPE SHARED)
+
+ELSEIF(TARGET_BUILD_PLATFORM STREQUAL "PS4")
+
+ SET(WW_PLATFORM_INCLUDES
+ $ENV{SCE_ORBIS_SDK_DIR}/target/include
+ )
+
+ SET(WW_COMPILE_DEFS
+
+ # Common to all configurations
+ _LIB;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;PX_PHYSX_STATIC_LIB;
+
+ $<$<CONFIG:debug>:_DEBUG;PX_DEBUG=1;PX_CHECKED=1;PX_SUPPORT_PVD=1;>
+ $<$<CONFIG:release>:NDEBUG;PX_SUPPORT_PVD=0;>
+ )
+
+ SET(WW_LIBTYPE STATIC)
+
+ELSEIF(TARGET_BUILD_PLATFORM STREQUAL "XBoxOne")
+ SET(WW_PLATFORM_INCLUDES
+ )
+
+ # Use generator expressions to set config specific preprocessor definitions
+ SET(WW_COMPILE_DEFS
+
+ # Common to all configurations
+ PX_PHYSX_CORE_EXPORTS;_LIB;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;WINAPI_FAMILY=WINAPI_FAMILY_TV_TITLE;PX_PHYSX_STATIC_LIB;
+
+ $<$<CONFIG:debug>:_DEBUG;PX_DEBUG=1;PX_CHECKED=1;PX_SUPPORT_PVD=1;>
+ $<$<CONFIG:release>:NDEBUG;PX_SUPPORT_PVD=0;>
+ )
+
+ SET(WW_LIBTYPE STATIC)
+
+
+ELSEIF(TARGET_BUILD_PLATFORM STREQUAL "Unix")
+ENDIF()
+
+SET(APP_FILES
+ ${SAMP_SOURCE_DIR}/math_code.cpp
+ ${SAMP_SOURCE_DIR}/math_code.h
+
+ ${SAMP_SOURCE_DIR}/ocean_surface.cpp
+ ${SAMP_SOURCE_DIR}/ocean_surface.h
+
+ ${SAMP_SOURCE_DIR}/sample_opengl.cpp
+
+ ${SAMP_SOURCE_DIR}/water.glsl
+)
+
+
+ADD_EXECUTABLE(SampleOpenGL WIN32
+ ${WW_PLATFORM_SRC_FILES}
+
+ ${APP_FILES}
+
+)
+
+SOURCE_GROUP("app" FILES ${APP_FILES})
+
+
+
+# Target specific compile options
+
+
+TARGET_INCLUDE_DIRECTORIES(SampleOpenGL
+ PRIVATE ${WW_PLATFORM_INCLUDES}
+
+ PRIVATE ${ATB_INCLUDE_DIRS}
+ PRIVATE ${TL_INCLUDE_DIR}
+)
+
+TARGET_COMPILE_DEFINITIONS(SampleOpenGL
+
+ # Common to all configurations
+ PRIVATE ${WW_COMPILE_DEFS}
+)
+
+
+
+#TODO: Link flags
+
+IF(TARGET_BUILD_PLATFORM STREQUAL "Windows")
+ # Add linked libraries
+ TARGET_LINK_LIBRARIES(SampleOpenGL PUBLIC WaveWorks comctl32.lib opengl32.lib ${ATB_LIBRARIES})
+
+ IF(CMAKE_CL_64)
+ SET(LIBPATH_SUFFIX "win64")
+ ELSE(CMAKE_CL_64)
+ SET(LIBPATH_SUFFIX "Win32")
+ ENDIF(CMAKE_CL_64)
+
+ SET_TARGET_PROPERTIES(SampleOpenGL PROPERTIES
+ LINK_FLAGS_DEBUG "/MAP /DEBUG /SUBSYSTEM:CONSOLE"
+ LINK_FLAGS_RELEASE "/MAP /INCREMENTAL:NO /SUBSYSTEM:CONSOLE"
+ )
+
+ELSEIF(TARGET_BUILD_PLATFORM STREQUAL "PS4")
+# TARGET_LINK_LIBRARIES(SampleOpenGL PUBLIC LowLevel LowLevelAABB LowLevelCloth LowLevelDynamics LowLevelParticles SampleD3D11Common PxFoundation PxPvdSDK PxTask SceneQuery SimulationController)
+
+ELSEIF(TARGET_BUILD_PLATFORM STREQUAL "XBoxOne")
+
+# TARGET_LINK_LIBRARIES(SampleOpenGL PUBLIC LowLevel LowLevelAABB LowLevelCloth LowLevelDynamics LowLevelParticles SampleD3D11Common PxFoundation PxPvdSDK PxTask SceneQuery SimulationController)
+
+ELSEIF(TARGET_BUILD_PLATFORM STREQUAL "Unix")
+ENDIF()
+
+
diff --git a/sample/opengl/math_code.cpp b/sample/opengl/math_code.cpp
new file mode 100644
index 0000000..b744f48
--- /dev/null
+++ b/sample/opengl/math_code.cpp
@@ -0,0 +1,488 @@
+/*
+ * math_code.cpp
+ *
+ * Created on: 21.03.2011
+ * Author: ttcheblokov
+ */
+
+#include "math_code.h"
+
+void cutLowerHalfspace(float result[4][4], float level, float position, float viewmatrix[4][4], float projectionmatrix[4][4])
+{
+ float viewprojectionmatrix[4][4],tm[4][4],n[4][4]={1.0f,0.0f,0.0f,0.0f,0.0f,1.0f,0.0f,0.0f,0.0f,0.0f,1.0f,0.0f,0.0f,0.0f,0.0f,1.0f};
+ float cplane[4],clip_plane[4];
+
+ cplane[0]=0.0f;
+ cplane[1]=0.1f;
+ cplane[2]=0.0f;
+ cplane[3]=-level*0.1f;//+0.1f;
+
+ mat4Mat4Mul(viewprojectionmatrix, projectionmatrix, viewmatrix);
+ mat4Inverse(tm,viewprojectionmatrix);
+ mat4Vec4Mul(clip_plane,tm,cplane);
+
+ //clip_plane[0]/=cplane[1];
+ //clip_plane[1]/=cplane[1];
+ //clip_plane[2]/=cplane[1];
+ //clip_plane[3]/=cplane[1];
+
+ clip_plane[3] -= 1.0f;
+
+ if((level<position))
+ {
+ clip_plane[0] *= -1.0f;
+ clip_plane[1] *= -1.0f;
+ clip_plane[2] *= -1.0f;
+ clip_plane[3] *= -1.0f;
+ }
+
+ n[0][2]=clip_plane[0];
+ n[1][2]=clip_plane[1];
+ n[2][2]=clip_plane[2];
+ n[3][2]=clip_plane[3];
+
+ mat4Mat4Mul(result,n,projectionmatrix);
+}
+
+void cutUpperHalfspace(float result[4][4], float level, float position, float viewmatrix[4][4], float projectionmatrix[4][4])
+{
+ float viewprojectionmatrix[4][4],tm[4][4],n[4][4]={1.0f,0.0f,0.0f,0.0f,0.0f,1.0f,0.0f,0.0f,0.0f,0.0f,1.0f,0.0f,0.0f,0.0f,0.0f,1.0f};
+ float cplane[4],clip_plane[4];
+
+ cplane[0]=0.0f;
+ cplane[1]=-0.1f;
+ cplane[2]=0.0f;
+ cplane[3]=level*0.1f;//-0.1f;
+
+ mat4Mat4Mul(viewprojectionmatrix, projectionmatrix, viewmatrix);
+ mat4Inverse(tm,viewprojectionmatrix);
+ mat4Vec4Mul(clip_plane,tm,cplane);
+
+ //clip_plane[0]/=cplane[1];
+ //clip_plane[1]/=cplane[1];
+ //clip_plane[2]/=cplane[1];
+ //clip_plane[3]/=cplane[1];
+
+ clip_plane[3] -= 1.0f;
+
+ if((level>position))
+ {
+ clip_plane[0] *= -1.0f;
+ clip_plane[1] *= -1.0f;
+ clip_plane[2] *= -1.0f;
+ clip_plane[3] *= -1.0f;
+ }
+
+ n[0][2]=clip_plane[0];
+ n[1][2]=clip_plane[1];
+ n[2][2]=clip_plane[2];
+ n[3][2]=clip_plane[3];
+
+ mat4Mat4Mul(result,n,projectionmatrix);
+}
+
+void vec3CrossProductNormalized(float result[3], float a[3], float b[3])
+ {
+ float length;
+ result[0]=a[1]*b[2]-a[2]*b[1];
+ result[1]=a[2]*b[0]-a[0]*b[2];
+ result[2]=a[0]*b[1]-a[1]*b[0];
+ length=sqrt(result[0]*result[0]+result[1]*result[1]+result[2]*result[2]);
+ result[0]/=length;
+ result[1]/=length;
+ result[2]/=length;
+ }
+
+ void vec4Sub(float a[4], float b[4], float c[4])
+ {
+ a[0]=b[0]-c[0];
+ a[1]=b[1]-c[1];
+ a[2]=b[2]-c[2];
+ a[3]=b[3]-c[3];
+ }
+ void vec4Add(float a[4], float b[4], float c[4])
+ {
+ a[0]=b[0]+c[0];
+ a[1]=b[1]+c[1];
+ a[2]=b[2]+c[2];
+ a[3]=b[3]+c[3];
+ }
+ float vec4DotProduct(float a[4], float b[4])
+ {
+ return (a[0]*b[0]+a[1]*b[1]+a[2]*b[2]+a[3]*b[3]);
+ }
+
+ float vec3DotProduct(float a[3], float b[3])
+ {
+ return (a[0]*b[0]+a[1]*b[1]+a[2]*b[2]);
+ }
+
+ void vec4Normalize(float a[4])
+ {
+ float length;
+ length=sqrt(a[0]*a[0]+a[1]*a[1]+a[2]*a[2]+a[3]*a[3]);
+ a[0]/=length;
+ a[1]/=length;
+ a[2]/=length;
+ a[3]/=length;
+ }
+ void vec3Normalize(float a[4])
+ {
+ float length;
+ length=sqrt(a[0]*a[0]+a[1]*a[1]+a[2]*a[2]);
+ a[0]/=length;
+ a[1]/=length;
+ a[2]/=length;
+ }
+ void mat4Add(float result[4][4], float a[4][4], float b[4][4])
+ {
+ int i,j;
+ for (i=0;i<4;++i)
+ for (j=0;j<4;++j)
+ result[i][j]=a[i][j]+b[i][j];
+ }
+ void mat4ConstMul(float result[4][4], float a[4][4], float b)
+ {
+ int i,j;
+ for (i=0;i<4;++i)
+ for (j=0;j<4;++j)
+ result[i][j]=a[i][j]*b;
+ }
+ void mat4Transpose(float result[4][4], float a[4][4])
+ {
+ int i,j;
+ for (i=0;i<4;++i)
+ for (j=0;j<4;++j)
+ result[i][j]=a[j][i];
+ }
+ void mat4Mat4Mul(float result[4][4], float a[4][4], float b[4][4])
+ {
+ int i,j,k;
+ float temp;
+
+ for (i=0;i<4;++i)
+ for (j=0;j<4;++j)
+ {
+ temp=0;
+ for(k=0;k<4;++k)
+ {
+ temp+=a[k][j]*b[i][k];
+ }
+ result[i][j]=temp;
+ }
+ }
+ void vec4Mat4Mul(float result[4], float a[4], float b[4][4])
+ {
+ int i,k;
+ float temp;
+
+ for (i=0;i<4;++i)
+ {
+ temp=0;
+ for(k=0;k<4;++k)
+ {
+ temp+=a[k]*b[k][i];
+ }
+ result[i]=temp;
+ }
+ }
+ void mat4Vec4Mul(float result[4], float a[4][4], float b[4])
+ {
+ int i,k;
+ float temp;
+ for (i=0;i<4;++i)
+ {
+ temp=0;
+ for(k=0;k<4;++k)
+ {
+ temp+=a[i][k]*b[k];
+ }
+ result[i]=temp;
+ }
+ }
+ void mat4CreateIdentity (float result[4][4])
+ {
+ int i;
+ for (i=0;i<4;i++)
+ {
+ result[i][0] = 0;
+ result[i][1] = 0;
+ result[i][2] = 0;
+ result[i][3] = 0;
+ }
+ result [0][0] = 1;
+ result [1][1] = 1;
+ result [2][2] = 1;
+ result [3][3] = 1;
+ }
+ void mat4CreateScale (float result[4][4], float x, float y, float z)
+ {
+ int i;
+ for (i=0;i<4;i++)
+ {
+ result[i][0] = 0;
+ result[i][1] = 0;
+ result[i][2] = 0;
+ result[i][3] = 0;
+ }
+ result [0][0] = x;
+ result [1][1] = y;
+ result [2][2] = z;
+ result [3][3] = 1;
+ }
+
+ void mat4CreateTranslation (float result[4][4], float x, float y, float z)
+ {
+ int i;
+ for (i=0;i<4;i++)
+ {
+ result[i][0] = 0;
+ result[i][1] = 0;
+ result[i][2] = 0;
+ result[i][3] = 0;
+ }
+ result [3][0] = x;
+ result [3][1] = y;
+ result [3][2] = z;
+ result [0][0] = 1;
+ result [1][1] = 1;
+ result [2][2] = 1;
+ result [3][3] = 1;
+
+ }
+
+ void mat4CreateProjection (float result[4][4], float w, float h, float zn, float zf)
+ {
+ for (int i=0;i<4;i++)
+ {
+ result[i][0] = 0;
+ result[i][1] = 0;
+ result[i][2] = 0;
+ result[i][3] = 0;
+ }
+ result [0][0] = zn/w;
+ result [1][1] = zn/h;
+ result [2][2] = -(zf+zn)/(zf-zn);
+ result [3][2] = -2.0f*zf*zn/(zf-zn);
+ result [2][3] = -1.0f;
+ }
+
+ void mat4CreateView (float result[4][4], float eyepoint[3], float lookatpoint[3])
+ {
+ float xaxis[3];
+ float yaxis[3];
+ float zaxis[3];
+ float up[3] = {0.0f,0.0f, 1.0f};
+
+ zaxis[0] = - lookatpoint[0] + eyepoint[0];
+ zaxis[1] = - lookatpoint[1] + eyepoint[1];
+ zaxis[2] = - lookatpoint[2] + eyepoint[2];
+
+ vec3Normalize(zaxis);
+ vec3CrossProductNormalized(xaxis, up, zaxis);
+ vec3CrossProductNormalized(yaxis, zaxis, xaxis);
+
+ result[0][0] = xaxis[0];
+ result[0][1] = yaxis[0];
+ result[0][2] = zaxis[0];
+ result[0][3] = 0;
+ result[1][0] = xaxis[1];
+ result[1][1] = yaxis[1];
+ result[1][2] = zaxis[1];
+ result[1][3] = 0;
+ result[2][0] = xaxis[2];
+ result[2][1] = yaxis[2];
+ result[2][2] = zaxis[2];
+ result[2][3] = 0;
+ result[3][0] = -vec3DotProduct(xaxis,eyepoint);
+ result[3][1] = -vec3DotProduct(yaxis,eyepoint);
+ result[3][2] = -vec3DotProduct(zaxis,eyepoint);
+ result[3][3] = 1.0f;
+ }
+
+ void mat4CreateOrthoProjection (float result[4][4], float xmin, float xmax, float ymin, float ymax, float zmin, float zmax)
+ {
+ for(int i=0;i<4;i++)
+ {
+ result[i][0]=0;
+ result[i][1]=0;
+ result[i][2]=0;
+ result[i][3]=0;
+ }
+ result[0][0] = 2.0f/(xmax-xmin);
+ result[1][1] = 2.0f/(ymax-ymin);
+ result[2][2] = -2.0f/(zmax-zmin);
+ result[3][3] = 1.0f;
+ result[3][0] = - (xmax + xmin) / (xmax - xmin);
+ result[3][1] = - (ymax + ymin) / (ymax - ymin);
+ result[3][2] = - (zmax + zmin) / (zmax - zmin);
+
+ }
+
+ void mat4CreateRotation (float result[4][4], float angle, char axis)
+ {
+ int i;
+ for (i=0;i<4;i++)
+ {
+ result[i][0] = 0;
+ result[i][1] = 0;
+ result[i][2] = 0;
+ result[i][3] = 0;
+ }
+ result [3][3] = 1;
+
+ switch (axis)
+ {
+ case 'x':
+ result[0][0]=1.0f;
+ result[0][1]=0.0f;
+ result[0][2]=0.0f;
+ result[1][0]=0.0f;
+ result[1][1]=cos(angle);
+ result[1][2]=sin(angle);
+ result[2][0]=0.0f;
+ result[2][1]=-sin(angle);
+ result[2][2]=cos(angle);
+ break;
+ case 'y':
+ result[0][0]=cos(angle);
+ result[0][1]=0.0f;
+ result[0][2]=-sin(angle);
+ result[1][0]=0.0f;
+ result[1][1]=1.0f;
+ result[1][2]=0.0f;
+ result[2][0]=sin(angle);
+ result[2][1]=0.0f;
+ result[2][2]=cos(angle);
+ break;
+ case 'z':
+ result[0][0]=cos(angle);
+ result[0][1]=sin(angle);
+ result[0][2]=0.0f;
+ result[1][0]=-sin(angle);
+ result[1][1]=cos(angle);
+ result[1][2]=0.0f;
+ result[2][0]=0.0f;
+ result[2][1]=0.0f;
+ result[2][2]=1.0f;
+ break;
+ }
+
+ }
+ float sgn (float a)
+ {
+ if(a>0.0f) return (1.0f);
+ if(a<0.0f) return (-1.0f);
+ return(0.0f);
+ }
+
+ float det2x2(float a,float b,
+ float c,float d)
+ {
+ return a * d - b * c;
+ }
+
+ float det3x3(float a1,float a2,float a3,
+ float b1,float b2,float b3,
+ float c1,float c2,float c3)
+ {
+ float ans;
+ ans = a1 * det2x2( b2, b3, c2, c3)
+ - b1 * det2x2( a2, a3, c2, c3)
+ + c1 * det2x2( a2, a3, b2, b3);
+ return ans;
+ }
+
+ float det4x4(float m[4][4])
+ {
+ float a1,a2,a3,a4,b1,b2,b3,b4,c1,c2,c3,c4,d1,d2,d3,d4;
+
+
+ a1 = m[0][0]; b1 = m[0][1];
+ c1 = m[0][2]; d1 = m[0][3];
+
+ a2 = m[1][0]; b2 = m[1][1];
+ c2 = m[1][2]; d2 = m[1][3];
+
+ a3 = m[2][0]; b3 = m[2][1];
+ c3 = m[2][2]; d3 = m[2][3];
+
+ a4 = m[3][0]; b4 = m[3][1];
+ c4 = m[3][2]; d4 = m[3][3];
+
+ return a1 * det3x3( b2, b3, b4, c2, c3, c4, d2, d3, d4)
+ - b1 * det3x3( a2, a3, a4, c2, c3, c4, d2, d3, d4)
+ + c1 * det3x3( a2, a3, a4, b2, b3, b4, d2, d3, d4)
+ - d1 * det3x3( a2, a3, a4, b2, b3, b4, c2, c3, c4);
+ }
+
+ void adjoint(float adj[4][4],float m[4][4])
+ {
+ float a1,a2,a3,a4,b1,b2,b3,b4,c1,c2,c3,c4,d1,d2,d3,d4;
+
+ a1 = m[0][0]; b1 = m[0][1];
+ c1 = m[0][2]; d1 = m[0][3];
+
+ a2 = m[1][0]; b2 = m[1][1];
+ c2 = m[1][2]; d2 = m[1][3];
+
+ a3 = m[2][0]; b3 = m[2][1];
+ c3 = m[2][2]; d3 = m[2][3];
+
+ a4 = m[3][0]; b4 = m[3][1];
+ c4 = m[3][2]; d4 = m[3][3];
+
+ adj[0][0] = det3x3( b2, b3, b4, c2, c3, c4, d2, d3, d4);
+ adj[1][0] = - det3x3( a2, a3, a4, c2, c3, c4, d2, d3, d4);
+ adj[2][0] = det3x3( a2, a3, a4, b2, b3, b4, d2, d3, d4);
+ adj[3][0] = - det3x3( a2, a3, a4, b2, b3, b4, c2, c3, c4);
+
+ adj[0][1] = - det3x3( b1, b3, b4, c1, c3, c4, d1, d3, d4);
+ adj[1][1] = det3x3( a1, a3, a4, c1, c3, c4, d1, d3, d4);
+ adj[2][1] = - det3x3( a1, a3, a4, b1, b3, b4, d1, d3, d4);
+ adj[3][1] = det3x3( a1, a3, a4, b1, b3, b4, c1, c3, c4);
+
+ adj[0][2] = det3x3( b1, b2, b4, c1, c2, c4, d1, d2, d4);
+ adj[1][2] = - det3x3( a1, a2, a4, c1, c2, c4, d1, d2, d4);
+ adj[2][2] = det3x3( a1, a2, a4, b1, b2, b4, d1, d2, d4);
+ adj[3][2] = - det3x3( a1, a2, a4, b1, b2, b4, c1, c2, c4);
+
+ adj[0][3] = - det3x3( b1, b2, b3, c1, c2, c3, d1, d2, d3);
+ adj[1][3] = det3x3( a1, a2, a3, c1, c2, c3, d1, d2, d3);
+ adj[2][3] = - det3x3( a1, a2, a3, b1, b2, b3, d1, d2, d3);
+ adj[3][3] = det3x3( a1, a2, a3, b1, b2, b3, c1, c2, c3);
+ }
+
+ void mat4Inverse(float result[4][4],float source[4][4])
+ {
+ float adj[4][4];
+ float det;
+ int i,j;
+
+ adjoint(adj,source);
+
+ det = det4x4(source);
+ if (fabs(det) < 1e-8f)
+ {
+ return ;
+ }
+ else
+ {
+ det = 1 / det;
+ for (i = 0; i < 4; i++)
+ for (j = 0; j < 4; j++)
+ result[i][j] = adj[i][j] * det;
+ }
+ }
+
+ void mat4Mat4Copy (float result[4][4], float source[4][4])
+ {
+ int i;
+ for (i=0;i<4;i++)
+ {
+ result[i][0] = source[i][0];
+ result[i][1] = source[i][1];
+ result[i][2] = source[i][2];
+ result[i][3] = source[i][3];
+ }
+ }
diff --git a/sample/opengl/math_code.h b/sample/opengl/math_code.h
new file mode 100644
index 0000000..e03da47
--- /dev/null
+++ b/sample/opengl/math_code.h
@@ -0,0 +1,49 @@
+/*
+ * math_code.h
+ *
+ * Created on: 21.03.2011
+ * Author: ttcheblokov
+ */
+#include <math.h>
+
+#ifndef MATH_CODE_H_
+#define MATH_CODE_H_
+
+// vector and matrix math functions
+ void cutLowerHalfspace(float result[4][4], float level, float position, float viewmatrix[4][4], float projectionmatrix[4][4]);
+ void cutUpperHalfspace(float result[4][4], float level, float position, float viewmatrix[4][4], float projectionmatrix[4][4]);
+ void vec3CrossProductNormalized(float result[3], float a[3], float b[3]);
+ void vec4Sub(float a[4], float b[4], float c[4]);
+ void vec4Add(float a[4], float b[4], float c[4]);
+ float vec3DotProduct(float a[3], float b[3]);
+ float vec4DotProduct(float a[4], float b[4]);
+ void vec4Normalize(float a[4]);
+ void vec3Normalize(float a[3]);
+ void mat4Add(float result[4][4], float a[4][4], float b[4][4]);
+ void mat4ConstMul(float result[4][4], float a[4][4], float b);
+ void mat4Transpose(float result[4][4], float a[4][4]);
+ void mat4Mat4Mul(float result[4][4], float a[4][4], float b[4][4]);
+ void vec4Mat4Mul(float result[4], float a[4], float b[4][4]);
+ void mat4Vec4Mul(float result[4], float a[4][4], float b[4]);
+ void mat4CreateIdentity (float result[4][4]);
+ void mat4CreateScale (float result[4][4], float x, float y, float z);
+ void mat4CreateTranslation (float result[4][4], float x, float y, float z);
+ void mat4CreateView(float result[4][4], float eyepoint[3], float lookatpoint[3]);
+ void mat4CreateProjection (float result[4][4], float w, float h, float zn, float zf);
+ void mat4CreateOrthoProjection (float result[4][4], float xmin, float xmax, float ymin, float ymax, float zmin, float zmax);
+ void mat4CreateRotation (float result[4][4], float angle, char axis);
+ void mat4Inverse(float result[4][4],float source[4][4]);
+ void mat4Mat4Copy (float result[4][4], float source[4][4]);
+
+ float sgn (float a);
+ float det2x2(float a,float b, float c,float d);
+ float det3x3(float a1,float a2,float a3,
+ float b1,float b2,float b3,
+ float c1,float c2,float c3);
+ float det4x4(float m[4][4]);
+ void adjoint(float adj[4][4],float m[4][4]);
+
+
+
+
+#endif /* MATH_CODE_H_ */
diff --git a/sample/opengl/ocean_surface.cpp b/sample/opengl/ocean_surface.cpp
new file mode 100644
index 0000000..8542e01
--- /dev/null
+++ b/sample/opengl/ocean_surface.cpp
Binary files differ
diff --git a/sample/opengl/ocean_surface.h b/sample/opengl/ocean_surface.h
new file mode 100644
index 0000000..945d2d7
--- /dev/null
+++ b/sample/opengl/ocean_surface.h
@@ -0,0 +1,345 @@
+// Copyright (c) 2011 NVIDIA Corporation. All rights reserved.
+//
+// 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, NONINFRINGEMENT,IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL NVIDIA
+// OR ITS SUPPLIERS BE LIABLE FOR ANY DIRECT, 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.
+//
+// Please direct any bugs or questions to [email protected]
+
+#include <GFSDK_WaveWorks.h>
+#include <windows.h>
+#include <stdio.h>
+#include <GL/gl.h>
+
+// types for GL functoins not defined in WaveWorks
+typedef void (APIENTRYP PFNGLCLEARDEPTHFPROC) (GLfloat d);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data);
+
+// GL constants
+#define GL_FRAMEBUFFER 0x8D40
+#define GL_TEXTURE0 0x84C0
+#define GL_COLOR_ATTACHMENT0 0x8CE0
+#define GL_FRAMEBUFFER_COMPLETE 0x8CD5
+#define GL_COMPILE_STATUS 0x8B81
+#define GL_LINK_STATUS 0x8B82
+#define GL_FRAGMENT_SHADER 0x8B30
+#define GL_VERTEX_SHADER 0x8B31
+#define GL_TESS_EVALUATION_SHADER 0x8E87
+#define GL_TESS_CONTROL_SHADER 0x8E88
+#define GL_GEOMETRY_SHADER 0x8DD9
+#define GL_ARRAY_BUFFER 0x8892
+#define GL_ELEMENT_ARRAY_BUFFER 0x8893
+#define GL_STATIC_DRAW 0x88E4
+#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1
+#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2
+#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3
+#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0
+#define GL_SHADING_LANGUAGE_VERSION 0x8B8C
+#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
+#define GL_ACTIVE_ATTRIBUTES 0x8B89
+
+// DDS file reading related structures
+typedef struct
+{
+ GLsizei width;
+ GLsizei height;
+ GLint components;
+ GLenum format;
+ GLint numMipmaps;
+ GLubyte *pixels;
+} gliGenericImage;
+
+#ifndef _DDSURFACEDESC2
+ // following structs & defines are copied from ddraw.h
+
+ #ifndef DUMMYUNIONNAMEN
+ #if defined(__cplusplus) || !defined(NONAMELESSUNION)
+ #define DUMMYUNIONNAMEN(n)
+ #else
+ #define DUMMYUNIONNAMEN(n) u##n
+ #endif
+ #endif
+
+ #ifndef MAKEFOURCC
+ #define MAKEFOURCC(ch0, ch1, ch2, ch3) \
+ ((DWORD)(BYTE)(ch0) | ((DWORD)(BYTE)(ch1) << 8) | \
+ ((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3) << 24 ))
+ #endif //defined(MAKEFOURCC)
+
+ #define DDSD_PIXELFORMAT 0x00001000l
+ #define DDSD_CAPS 0x00000001l
+ #define DDSD_HEIGHT 0x00000002l
+ #define DDSD_WIDTH 0x00000004l
+ #define DDSD_PITCH 0x00000008l
+ #define DDSD_MIPMAPCOUNT 0x00020000l
+ #define DDPF_FOURCC 0x00000004l
+ #define DDPF_RGB 0x00000040l
+ #define FOURCC_DXT1 (MAKEFOURCC('D','X','T','1'))
+ #define FOURCC_DXT2 (MAKEFOURCC('D','X','T','2'))
+ #define FOURCC_DXT3 (MAKEFOURCC('D','X','T','3'))
+ #define FOURCC_DXT4 (MAKEFOURCC('D','X','T','4'))
+ #define FOURCC_DXT5 (MAKEFOURCC('D','X','T','5'))
+
+ typedef struct _DDCOLORKEY
+ {
+ DWORD dwColorSpaceLowValue; // low boundary of color space that is to
+ // be treated as Color Key, inclusive
+ DWORD dwColorSpaceHighValue; // high boundary of color space that is
+ // to be treated as Color Key, inclusive
+ } DDCOLORKEY;
+
+ typedef struct _DDPIXELFORMAT
+ {
+ DWORD dwSize; // size of structure
+ DWORD dwFlags; // pixel format flags
+ DWORD dwFourCC; // (FOURCC code)
+ union
+ {
+ DWORD dwRGBBitCount; // how many bits per pixel
+ DWORD dwYUVBitCount; // how many bits per pixel
+ DWORD dwZBufferBitDepth; // how many total bits/pixel in z buffer (including any stencil bits)
+ DWORD dwAlphaBitDepth; // how many bits for alpha channels
+ DWORD dwLuminanceBitCount; // how many bits per pixel
+ DWORD dwBumpBitCount; // how many bits per "buxel", total
+ DWORD dwPrivateFormatBitCount;// Bits per pixel of private driver formats. Only valid in texture
+ // format list and if DDPF_D3DFORMAT is set
+ } DUMMYUNIONNAMEN(1);
+ union
+ {
+ DWORD dwRBitMask; // mask for red bit
+ DWORD dwYBitMask; // mask for Y bits
+ DWORD dwStencilBitDepth; // how many stencil bits (note: dwZBufferBitDepth-dwStencilBitDepth is total Z-only bits)
+ DWORD dwLuminanceBitMask; // mask for luminance bits
+ DWORD dwBumpDuBitMask; // mask for bump map U delta bits
+ DWORD dwOperations; // DDPF_D3DFORMAT Operations
+ } DUMMYUNIONNAMEN(2);
+ union
+ {
+ DWORD dwGBitMask; // mask for green bits
+ DWORD dwUBitMask; // mask for U bits
+ DWORD dwZBitMask; // mask for Z bits
+ DWORD dwBumpDvBitMask; // mask for bump map V delta bits
+ struct
+ {
+ WORD wFlipMSTypes; // Multisample methods supported via flip for this D3DFORMAT
+ WORD wBltMSTypes; // Multisample methods supported via blt for this D3DFORMAT
+ } MultiSampleCaps;
+
+ } DUMMYUNIONNAMEN(3);
+ union
+ {
+ DWORD dwBBitMask; // mask for blue bits
+ DWORD dwVBitMask; // mask for V bits
+ DWORD dwStencilBitMask; // mask for stencil bits
+ DWORD dwBumpLuminanceBitMask; // mask for luminance in bump map
+ } DUMMYUNIONNAMEN(4);
+ union
+ {
+ DWORD dwRGBAlphaBitMask; // mask for alpha channel
+ DWORD dwYUVAlphaBitMask; // mask for alpha channel
+ DWORD dwLuminanceAlphaBitMask;// mask for alpha channel
+ DWORD dwRGBZBitMask; // mask for Z channel
+ DWORD dwYUVZBitMask; // mask for Z channel
+ } DUMMYUNIONNAMEN(5);
+ } DDPIXELFORMAT;
+
+ typedef struct _DDSCAPS2
+ {
+ DWORD dwCaps; // capabilities of surface wanted
+ DWORD dwCaps2;
+ DWORD dwCaps3;
+ union
+ {
+ DWORD dwCaps4;
+ DWORD dwVolumeDepth;
+ } DUMMYUNIONNAMEN(1);
+ } DDSCAPS2;
+
+ typedef struct _DDSURFACEDESC2
+ {
+ DWORD dwSize; // size of the DDSURFACEDESC structure
+ DWORD dwFlags; // determines what fields are valid
+ DWORD dwHeight; // height of surface to be created
+ DWORD dwWidth; // width of input surface
+ union
+ {
+ LONG lPitch; // distance to start of next line (return value only)
+ DWORD dwLinearSize; // Formless late-allocated optimized surface size
+ } DUMMYUNIONNAMEN(1);
+ union
+ {
+ DWORD dwBackBufferCount; // number of back buffers requested
+ DWORD dwDepth; // the depth if this is a volume texture
+ } DUMMYUNIONNAMEN(5);
+ union
+ {
+ DWORD dwMipMapCount; // number of mip-map levels requestde
+ // dwZBufferBitDepth removed, use ddpfPixelFormat one instead
+ DWORD dwRefreshRate; // refresh rate (used when display mode is described)
+ DWORD dwSrcVBHandle; // The source used in VB::Optimize
+ } DUMMYUNIONNAMEN(2);
+ DWORD dwAlphaBitDepth; // depth of alpha buffer requested
+ DWORD dwReserved; // reserved
+ DWORD lpSurface; // pointer to the associated surface memory
+ union
+ {
+ DDCOLORKEY ddckCKDestOverlay; // color key for destination overlay use
+ DWORD dwEmptyFaceColor; // Physical color for empty cubemap faces
+ } DUMMYUNIONNAMEN(3);
+ DDCOLORKEY ddckCKDestBlt; // color key for destination blt use
+ DDCOLORKEY ddckCKSrcOverlay; // color key for source overlay use
+ DDCOLORKEY ddckCKSrcBlt; // color key for source blt use
+ union
+ {
+ DDPIXELFORMAT ddpfPixelFormat; // pixel format description of the surface
+ DWORD dwFVF; // vertex format description of vertex buffers
+ } DUMMYUNIONNAMEN(4);
+ DDSCAPS2 ddsCaps; // direct draw surface capabilities
+ DWORD dwTextureStage; // stage in multitexture cascade
+ } DDSURFACEDESC2;
+#endif
+
+
+class OceanSurface
+{
+ public:
+ OceanSurface(bool use_texture_arrays);
+ ~OceanSurface();
+
+ // Quadtree handle and shader mappings
+ GFSDK_WaveWorks_QuadtreeHandle hOceanQuadTree;
+ UINT* pQuadTreeShaderInputMappings;
+ UINT* pSimulationShaderInputMappings;
+
+ // Quadtree initialization
+ gfsdk_waveworks_result InitQuadTree(const GFSDK_WaveWorks_Quadtree_Params& params);
+
+
+ // Initializing OpenGL functions addresses
+ HRESULT InitGLFunctions(void);
+
+ // Creating OpenGL programs
+ GLuint LoadProgram(char *);
+ GLuint CompileShader(char *text, GLenum type);
+
+ // Texture loading related methods
+ int LoadTexture(char * filename, GLuint * texID);
+ void CreateTextures(void);
+
+ // Rendering related methods
+ void SetupNormalView(void);
+ void Render(GFSDK_WaveWorks_SimulationHandle hSim, GFSDK_WaveWorks_Simulation_Settings settings, bool Wireframe);
+
+ // Constants
+ UINT ScreenWidth;
+ UINT ScreenHeight;
+ UINT MultiSampleCount;
+ UINT MultiSampleQuality;
+
+ // Programs
+ GLuint WaterProgram;
+
+ // Textures
+ GLuint FoamIntensityTextureID;
+ GLuint FoamIntensityTextureBindLocation;
+ GLuint FoamDiffuseTextureID;
+ GLuint FoamDiffuseTextureBindLocation;
+
+ // GL resources allocated for WaveWorks during ocean surface rendering
+ GFSDK_WaveWorks_Simulation_GL_Pool glPool;
+
+ // Camera reated variables
+ float CameraPosition[3];
+ float LookAtPosition[3];
+
+ float NormalViewMatrix[4][4];
+ float NormalProjMatrix[4][4];
+ float NormalViewProjMatrix[4][4];
+
+ // Counters
+ double total_time;
+ float delta_time;
+
+ // Input
+ int MouseX,MouseY;
+ float MouseDX,MouseDY;
+ float Alpha;
+ float Beta;
+
+ // GL functions
+ PFNGLACTIVETEXTUREPROC glActiveTexture;
+ PFNGLATTACHSHADERPROC glAttachShader;
+ PFNGLBINDBUFFERPROC glBindBuffer;
+ PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer;
+ PFNGLBINDTEXTUREPROC glBindTexture;
+ PFNGLBUFFERDATAPROC glBufferData;
+ PFNGLCHECKFRAMEBUFFERSTATUSPROC glCheckFramebufferStatus;
+ PFNGLCLEARCOLORPROC glClearColor;
+ PFNGLCLEARDEPTHFPROC glClearDepthf;
+ PFNGLCLEARPROC glClear;
+ PFNGLCOLORMASKPROC glColorMask;
+ PFNGLCOMPILESHADERPROC glCompileShader;
+ PFNGLCOMPRESSEDTEXIMAGE2DPROC glCompressedTexImage2D;
+ PFNGLCREATEPROGRAMPROC glCreateProgram;
+ PFNGLCREATESHADERPROC glCreateShader;
+ PFNGLDELETEBUFFERSPROC glDeleteBuffers;
+ PFNGLDELETEFRAMEBUFFERSPROC glDeleteFramebuffers;
+ PFNGLDELETEPROGRAMPROC glDeleteProgram;
+ PFNGLDELETESHADERPROC glDeleteShader;
+ PFNGLDELETETEXTURESPROC glDeleteTextures;
+ PFNGLDISABLEPROC glDisable;
+ PFNGLDISABLEVERTEXATTRIBARRAYPROC glDisableVertexAttribArray;
+ PFNGLDRAWELEMENTSPROC glDrawElements;
+ PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray;
+ PFNGLFRAMEBUFFERTEXTURE2DPROC glFramebufferTexture2D;
+ PFNGLGENBUFFERSPROC glGenBuffers;
+ PFNGLGENERATEMIPMAPPROC glGenerateMipmap;
+ PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers;
+ PFNGLGENTEXTURESPROC glGenTextures;
+ PFNGLGETATTRIBLOCATIONPROC glGetAttribLocation;
+ PFNGLGETERRORPROC glGetError;
+ PFNGLGETINTEGERVPROC glGetIntegerv;
+ PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog;
+ PFNGLGETPROGRAMIVPROC glGetProgramiv;
+ PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog;
+ PFNGLGETSHADERIVPROC glGetShaderiv;
+ PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation;
+ PFNGLLINKPROGRAMPROC glLinkProgram;
+ PFNGLMAPBUFFERRANGEPROC glMapBufferRange;
+ PFNGLPATCHPARAMETERIPROC glPatchParameteri;
+ PFNGLSHADERSOURCEPROC glShaderSource;
+ PFNGLTEXIMAGE2DPROC glTexImage2D;
+ PFNGLTEXPARAMETERFPROC glTexParameterf;
+ PFNGLTEXPARAMETERIPROC glTexParameteri;
+ PFNGLTEXSUBIMAGE2DPROC glTexSubImage2D;
+ PFNGLUNIFORM1FPROC glUniform1f;
+ PFNGLUNIFORM1IPROC glUniform1i;
+ PFNGLUNIFORM3FVPROC glUniform3fv;
+ PFNGLUNIFORM4FVPROC glUniform4fv;
+ PFNGLUNIFORMMATRIX3X4FVPROC glUniformMatrix3x4fv;
+ PFNGLUNIFORMMATRIX4FVPROC glUniformMatrix4fv;
+ PFNGLUNMAPBUFFERPROC glUnmapBuffer;
+ PFNGLUSEPROGRAMPROC glUseProgram;
+ PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer;
+ PFNGLVIEWPORTPROC glViewport;
+ PFNGLGENQUERIESPROC glGenQueries;
+ PFNGLDELETEQUERIESPROC glDeleteQueries;
+ PFNGLQUERYCOUNTERPROC glQueryCounter;
+ PFNGLGETQUERYOBJECTUI64VPROC glGetQueryObjectui64v;
+ PFNGLGETACTIVEATTRIBPROC glGetActiveAttrib;
+ PFNGLFRAMEBUFFERTEXTURELAYERPROC glFramebufferTextureLayer;
+ PFNGLTEXIMAGE3DPROC glTexImage3D;
+ PFNGLBLITFRAMEBUFFERPROC glBlitFramebuffer;
+ PFNGLREADBUFFERPROC glReadBuffer;
+ PFNGLDRAWBUFFERSPROC glDrawBuffers;
+};
+
+void checkError(const char *);
+
diff --git a/sample/opengl/sample_opengl.cpp b/sample/opengl/sample_opengl.cpp
new file mode 100644
index 0000000..8bcebf6
--- /dev/null
+++ b/sample/opengl/sample_opengl.cpp
@@ -0,0 +1,850 @@
+// ocean_cufft_app.cpp : Defines the entry point for the console application.
+//
+
+#include "math_code.h"
+#include "ocean_surface.h"
+#include "GFSDK_WaveWorks.h"
+#include <windows.h> // for QueryPerformanceFrequency/QueryPerformanceCounter
+#include "AntTweakBar.h"
+
+#ifndef PI
+#define PI 3.14159265358979323846f
+#endif
+
+OceanSurface* g_pOceanSurf = NULL;
+GFSDK_WaveWorks_SimulationHandle g_hOceanSimulation = NULL;
+GFSDK_WaveWorks_Simulation_Params g_ocean_simulation_param;
+GFSDK_WaveWorks_Simulation_Settings g_ocean_simulation_settings;
+GFSDK_WaveWorks_Quadtree_Params g_ocean_param_quadtree;
+GFSDK_WaveWorks_Quadtree_Stats g_ocean_stats_quadtree;
+GFSDK_WaveWorks_Simulation_Stats g_ocean_stats_simulation;
+GFSDK_WaveWorks_Simulation_Stats g_ocean_stats_simulation_filtered;
+GFSDK_WAVEWORKS_GLFunctions g_GLFunctions;
+int g_max_detail_level;
+long g_FPS;
+long g_Second;
+long g_FrameNumber;
+
+HINSTANCE g_hInstance; // GL window class instance
+HWND g_hWnd; // GL window class handle
+HDC g_hDC; // GL window device context handle
+HGLRC g_hRC; // GL rendering context
+LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); // forward declaration For WndProc
+bool g_ExitApp = false;
+bool g_WindowActive = true;
+MSG g_Msg; // Windows message structure
+bool g_PressedKeys[256]; // Array of pressed keys
+
+TwBar* g_pStatsBar;
+TwBar* g_pControlsBar;
+
+// Controls
+bool g_Wireframe = false;
+bool g_SimulateWater = true;
+bool g_ShowStats = false;
+
+// Callbacks for Controls AntTweakBar
+static void TW_CALL CB_SetShowStats(const void *value, void * /*clientData*/)
+{
+ g_ShowStats = *(const bool *)value;
+ if(g_ShowStats)
+ {
+ TwDefine("Stats visible=true");
+ }
+ else
+ {
+ TwDefine("Stats visible=false");
+ }
+}
+static void TW_CALL CB_GetShowStats(void *value, void * /*clientData*/)
+{
+ *(bool *)value = g_ShowStats;
+}
+
+static void TW_CALL CB_SetUseBeaufort(const void *value, void * /*clientData*/)
+{
+ g_ocean_simulation_settings.use_Beaufort_scale = *(const bool *)value;
+ if(g_ocean_simulation_settings.use_Beaufort_scale)
+ {
+ g_ocean_simulation_param.wind_speed = min(12.0f, g_ocean_simulation_param.wind_speed);
+ TwDefine("Controls/'Wind Speed' min=0 max = 12 step=0.1 precision=1");
+ TwDefine("Controls/'Wave Amplitude' visible = false");
+ TwDefine("Controls/'Chop Scale' visible = false");
+ }
+ else
+ {
+ TwDefine("Controls/'Wind Speed' min=0 max = 50 step=0.1 precision=1");
+ TwDefine("Controls/'Wave Amplitude' visible = true");
+ TwDefine("Controls/'Chop Scale' visible = true");
+ }
+ GFSDK_WaveWorks_Simulation_UpdateProperties(g_hOceanSimulation, g_ocean_simulation_settings, g_ocean_simulation_param);
+ GFSDK_WaveWorks_Quadtree_SetFrustumCullMargin(g_pOceanSurf->hOceanQuadTree, GFSDK_WaveWorks_Simulation_GetConservativeMaxDisplacementEstimate(g_hOceanSimulation));
+}
+static void TW_CALL CB_GetUseBeaufort(void *value, void * /*clientData*/)
+{
+ *(bool *)value = g_ocean_simulation_settings.use_Beaufort_scale;
+}
+
+static void TW_CALL CB_SetWaveAmplitude(const void *value, void * /*clientData*/)
+{
+ g_ocean_simulation_param.wave_amplitude = *(const float *)value;
+ GFSDK_WaveWorks_Simulation_UpdateProperties(g_hOceanSimulation, g_ocean_simulation_settings, g_ocean_simulation_param);
+ GFSDK_WaveWorks_Quadtree_SetFrustumCullMargin(g_pOceanSurf->hOceanQuadTree, GFSDK_WaveWorks_Simulation_GetConservativeMaxDisplacementEstimate(g_hOceanSimulation));
+}
+static void TW_CALL CB_GetWaveAmplitude(void *value, void * /*clientData*/)
+{
+ *(float *)value = g_ocean_simulation_param.wave_amplitude;
+}
+
+static void TW_CALL CB_SetChopScale(const void *value, void * /*clientData*/)
+{
+ g_ocean_simulation_param.choppy_scale = *(const float *)value;
+ GFSDK_WaveWorks_Simulation_UpdateProperties(g_hOceanSimulation, g_ocean_simulation_settings, g_ocean_simulation_param);
+}
+static void TW_CALL CB_GetChopScale(void *value, void * /*clientData*/)
+{
+ *(float *)value = g_ocean_simulation_param.choppy_scale;
+}
+
+static void TW_CALL CB_SetWindSpeed(const void *value, void * /*clientData*/)
+{
+ g_ocean_simulation_param.wind_speed = *(const float *)value;
+ GFSDK_WaveWorks_Simulation_UpdateProperties(g_hOceanSimulation, g_ocean_simulation_settings, g_ocean_simulation_param);
+ GFSDK_WaveWorks_Quadtree_SetFrustumCullMargin(g_pOceanSurf->hOceanQuadTree, GFSDK_WaveWorks_Simulation_GetConservativeMaxDisplacementEstimate(g_hOceanSimulation));
+}
+static void TW_CALL CB_GetWindSpeed(void *value, void * /*clientData*/)
+{
+ *(float *)value = g_ocean_simulation_param.wind_speed;
+}
+
+static void TW_CALL CB_SetWindDependency(const void *value, void * /*clientData*/)
+{
+ g_ocean_simulation_param.wind_dependency = *(const float *)value;
+ GFSDK_WaveWorks_Simulation_UpdateProperties(g_hOceanSimulation, g_ocean_simulation_settings, g_ocean_simulation_param);
+ GFSDK_WaveWorks_Quadtree_SetFrustumCullMargin(g_pOceanSurf->hOceanQuadTree, GFSDK_WaveWorks_Simulation_GetConservativeMaxDisplacementEstimate(g_hOceanSimulation));
+}
+static void TW_CALL CB_GetWindDependency(void *value, void * /*clientData*/)
+{
+ *(float *)value = g_ocean_simulation_param.wind_dependency;
+}
+
+static void TW_CALL CB_SetTimeScale(const void *value, void * /*clientData*/)
+{
+ g_ocean_simulation_param.time_scale = *(const float *)value;
+ GFSDK_WaveWorks_Simulation_UpdateProperties(g_hOceanSimulation, g_ocean_simulation_settings, g_ocean_simulation_param);
+}
+static void TW_CALL CB_GetTimeScale(void *value, void * /*clientData*/)
+{
+ *(float *)value = g_ocean_simulation_param.time_scale;
+}
+
+static void TW_CALL CB_SetAnisoLevel(const void *value, void * /*clientData*/)
+{
+ g_ocean_simulation_settings.aniso_level = *(const gfsdk_U8 *)value;
+ GFSDK_WaveWorks_Simulation_UpdateProperties(g_hOceanSimulation, g_ocean_simulation_settings, g_ocean_simulation_param);
+}
+static void TW_CALL CB_GetAnisoLevel(void *value, void * /*clientData*/)
+{
+ *(gfsdk_U8 *)value = g_ocean_simulation_settings.aniso_level;
+}
+
+static void TW_CALL CB_SetDetailLevel(const void *value, void * /*clientData*/)
+{
+ if(GFSDK_WaveWorks_Simulation_DetailLevelIsSupported_GL2(*(const GFSDK_WaveWorks_Simulation_DetailLevel *)value))
+ {
+ g_ocean_simulation_settings.detail_level = *(const GFSDK_WaveWorks_Simulation_DetailLevel *)value;
+ GFSDK_WaveWorks_Simulation_UpdateProperties(g_hOceanSimulation, g_ocean_simulation_settings, g_ocean_simulation_param);
+ }
+}
+static void TW_CALL CB_GetDetailLevel(void *value, void * /*clientData*/)
+{
+ *(gfsdk_U8 *)value = (gfsdk_U8)g_ocean_simulation_settings.detail_level;
+}
+
+// Helper functions
+void PrintGLInfo(void)
+{
+ printf ("\nVendor: %s", glGetString (GL_VENDOR));
+ printf ("\nRenderer: %s", glGetString (GL_RENDERER));
+ printf ("\nVersion: %s", glGetString (GL_VERSION));
+ printf ("\nGLSL: %s", glGetString (GL_SHADING_LANGUAGE_VERSION));
+ checkError ("dumpInfo");
+}
+
+// Rendering functions
+void RenderFrame(void)
+{
+ static LARGE_INTEGER freq, counter, old_counter;
+
+ if(g_SimulateWater)
+ do {
+ GFSDK_WaveWorks_Simulation_SetTime(g_hOceanSimulation, g_pOceanSurf->total_time);
+ GFSDK_WaveWorks_Simulation_KickGL2(g_hOceanSimulation, NULL);
+ } while(gfsdk_waveworks_result_NONE==GFSDK_WaveWorks_Simulation_GetStagingCursor(g_hOceanSimulation,NULL));
+
+ // getting simulation timings
+ GFSDK_WaveWorks_Simulation_GetStats(g_hOceanSimulation,g_ocean_stats_simulation);
+
+ // rendering
+ g_pOceanSurf->Render(g_hOceanSimulation, g_ocean_simulation_settings, g_Wireframe);
+
+ // getting quadtree stats
+ GFSDK_WaveWorks_Quadtree_GetStats(g_pOceanSurf->hOceanQuadTree, g_ocean_stats_quadtree);
+
+ // Drawing AntTweakBars
+ TwDraw();
+ SwapBuffers(g_hDC);
+ g_FrameNumber++;
+
+ // timing
+ QueryPerformanceFrequency(&freq);
+ QueryPerformanceCounter(&counter);
+
+ g_pOceanSurf->delta_time = (float)(((double)(counter.QuadPart) - (double)(old_counter.QuadPart))/(double)freq.QuadPart);
+ g_pOceanSurf->total_time += g_pOceanSurf->delta_time;
+ if(g_pOceanSurf->total_time>=36000.0f) g_pOceanSurf->total_time=0;
+ old_counter = counter;
+
+ if((long)(floor(g_pOceanSurf->total_time)) > g_Second)
+ {
+ g_FPS = g_FrameNumber/((long)(floor(g_pOceanSurf->total_time)) - g_Second);
+ g_Second = (long)(ceil(g_pOceanSurf->total_time));
+ g_FrameNumber = 0;
+ }
+
+ // exponential filtering for stats
+ g_ocean_stats_simulation_filtered.CPU_main_thread_wait_time = g_ocean_stats_simulation_filtered.CPU_main_thread_wait_time*0.98f + 0.02f*g_ocean_stats_simulation.CPU_main_thread_wait_time;
+ g_ocean_stats_simulation_filtered.CPU_threads_start_to_finish_time = g_ocean_stats_simulation_filtered.CPU_threads_start_to_finish_time*0.98f + 0.02f*g_ocean_stats_simulation.CPU_threads_start_to_finish_time;
+ g_ocean_stats_simulation_filtered.CPU_threads_total_time = g_ocean_stats_simulation_filtered.CPU_threads_total_time*0.98f + 0.02f*g_ocean_stats_simulation.CPU_threads_total_time;
+ g_ocean_stats_simulation_filtered.GPU_simulation_time = g_ocean_stats_simulation_filtered.GPU_simulation_time*0.98f + 0.02f*g_ocean_stats_simulation.GPU_simulation_time;
+ g_ocean_stats_simulation_filtered.GPU_FFT_simulation_time = g_ocean_stats_simulation_filtered.GPU_FFT_simulation_time*0.98f + 0.02f*g_ocean_stats_simulation.GPU_FFT_simulation_time;
+ g_ocean_stats_simulation_filtered.GPU_gfx_time = g_ocean_stats_simulation_filtered.GPU_gfx_time*0.98f + 0.02f*g_ocean_stats_simulation.GPU_gfx_time;
+ g_ocean_stats_simulation_filtered.GPU_update_time = g_ocean_stats_simulation_filtered.GPU_update_time*0.98f + 0.02f*g_ocean_stats_simulation.GPU_update_time;
+}
+
+// Input functions
+void ProcessWSADKeys()
+{
+ if(g_pOceanSurf)
+ {
+ float direction[3];
+ float strafe[3];
+ float up[3] = {0.0f,0.0f,1.0f};
+
+ direction[0]=g_pOceanSurf->LookAtPosition[0] - g_pOceanSurf->CameraPosition[0];
+ direction[1]=g_pOceanSurf->LookAtPosition[1] - g_pOceanSurf->CameraPosition[1];
+ direction[2]=g_pOceanSurf->LookAtPosition[2] - g_pOceanSurf->CameraPosition[2];
+ vec3Normalize(direction);
+ vec3CrossProductNormalized(strafe,up,direction);
+
+ if(g_PressedKeys[87]) //'w'
+ {
+ g_pOceanSurf->CameraPosition[0]+=0.5f*direction[0];
+ g_pOceanSurf->CameraPosition[1]+=0.5f*direction[1];
+ g_pOceanSurf->CameraPosition[2]+=0.5f*direction[2];
+ g_pOceanSurf->LookAtPosition[0]+=0.5f*direction[0];
+ g_pOceanSurf->LookAtPosition[1]+=0.5f*direction[1];
+ g_pOceanSurf->LookAtPosition[2]+=0.5f*direction[2];
+ }
+ if(g_PressedKeys[83]) //'s'
+ {
+ g_pOceanSurf->CameraPosition[0]-=0.5f*direction[0];
+ g_pOceanSurf->CameraPosition[1]-=0.5f*direction[1];
+ g_pOceanSurf->CameraPosition[2]-=0.5f*direction[2];
+ g_pOceanSurf->LookAtPosition[0]-=0.5f*direction[0];
+ g_pOceanSurf->LookAtPosition[1]-=0.5f*direction[1];
+ g_pOceanSurf->LookAtPosition[2]-=0.5f*direction[2];
+ }
+ if(g_PressedKeys[65]) //'a'
+ {
+ g_pOceanSurf->CameraPosition[0]+=0.5f*strafe[0];
+ g_pOceanSurf->CameraPosition[1]+=0.5f*strafe[1];
+ g_pOceanSurf->CameraPosition[2]+=0.5f*strafe[2];
+ g_pOceanSurf->LookAtPosition[0]+=0.5f*strafe[0];
+ g_pOceanSurf->LookAtPosition[1]+=0.5f*strafe[1];
+ g_pOceanSurf->LookAtPosition[2]+=0.5f*strafe[2];
+ }
+ if(g_PressedKeys[68]) //'d'
+ {
+ g_pOceanSurf->CameraPosition[0]-=0.5f*strafe[0];
+ g_pOceanSurf->CameraPosition[1]-=0.5f*strafe[1];
+ g_pOceanSurf->CameraPosition[2]-=0.5f*strafe[2];
+ g_pOceanSurf->LookAtPosition[0]-=0.5f*strafe[0];
+ g_pOceanSurf->LookAtPosition[1]-=0.5f*strafe[1];
+ g_pOceanSurf->LookAtPosition[2]-=0.5f*strafe[2];
+ }
+ }
+}
+
+void ProcessMouseMotion(int MouseX, int MouseY, int LButtonPressed)
+{
+ if(g_pOceanSurf)
+ {
+ float initial_direction[4]={1.0f,0.0f,0.0f,1.0f};
+ float direction[4];
+ float r1[4][4],r2[4][4],rotation[4][4];
+
+ if(LButtonPressed)
+ {
+ g_pOceanSurf->MouseDX = (float)MouseX - (float)g_pOceanSurf->MouseX;
+ g_pOceanSurf->MouseDY = (float)MouseY - (float)g_pOceanSurf->MouseY;
+ }
+ else
+ {
+ g_pOceanSurf->MouseDX = 0;
+ g_pOceanSurf->MouseDY = 0;
+ }
+ g_pOceanSurf->MouseX = MouseX;
+ g_pOceanSurf->MouseY = MouseY;
+
+
+ g_pOceanSurf->Alpha+=g_pOceanSurf->MouseDX*0.002f;
+ g_pOceanSurf->Beta+=g_pOceanSurf->MouseDY*0.002f;
+ if(g_pOceanSurf->Beta>PI*0.49f)g_pOceanSurf->Beta = PI*0.49f;
+ if(g_pOceanSurf->Beta<-PI*0.49f)g_pOceanSurf->Beta = -PI*0.49f;
+ mat4CreateRotation(r1,g_pOceanSurf->Alpha,'z');
+ mat4CreateRotation(r2,-g_pOceanSurf->Beta,'y');
+ mat4Mat4Mul(rotation,r1,r2);
+ vec4Mat4Mul(direction,initial_direction,rotation);
+ g_pOceanSurf->LookAtPosition[0]=g_pOceanSurf->CameraPosition[0]+direction[0];
+ g_pOceanSurf->LookAtPosition[1]=g_pOceanSurf->CameraPosition[1]+direction[1];
+ g_pOceanSurf->LookAtPosition[2]=g_pOceanSurf->CameraPosition[2]+direction[2];
+ }
+}
+
+// GL Window related functions
+void KillGLWindow(void)
+{
+ // do we have a rendering context?
+ if (g_hRC)
+ {
+ // are we able to release the DC and RC?
+ if (!wglMakeCurrent(NULL,NULL))
+ {
+ MessageBox(NULL,L"Release of DC and RC failed.",L"SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
+ }
+ // are we able to delete the RC?
+ if (!wglDeleteContext(g_hRC))
+ {
+ MessageBox(NULL,L"Release rendering context failed.",L"SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
+ }
+ g_hRC = NULL;
+ }
+
+ // are we able to release the DC
+ if (g_hDC && !ReleaseDC(g_hWnd,g_hDC))
+ {
+ MessageBox(NULL,L"Release device context failed.",L"SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
+ g_hDC = NULL;
+ }
+
+ // are we able to destroy the window?
+ if (g_hWnd && !DestroyWindow(g_hWnd))
+ {
+ MessageBox(NULL,L"Could not release window handle.",L"SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
+ g_hWnd = NULL;
+ }
+
+ // are we able to unregister class?
+ if (!UnregisterClass(L"OpenGL",g_hInstance))
+ {
+ MessageBox(NULL,L"Could not unregister class.",L"SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
+ g_hInstance = NULL;
+ }
+}
+
+BOOL CreateGLWindow(LPCWSTR title, int width, int height, byte bpp)
+{
+ GLuint PixelFormat; // holds the results after searching for a match
+ WNDCLASS wc; // windows class structure
+ DWORD dwExStyle; // window extended style
+ DWORD dwStyle; // window style
+ RECT WindowRect; // grabs rectangle upper left / lower right values
+ WindowRect.left=(long)0; // set left value to 0
+ WindowRect.right=(long)width; // set right value to requested width
+ WindowRect.top=(long)0; // set top value to 0
+ WindowRect.bottom=(long)height; // set bottom value to requested height
+
+ g_hInstance = GetModuleHandle(NULL); // grab an instance for our window
+ wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; // redraw on size, and own DC for window.
+ wc.lpfnWndProc = (WNDPROC) WndProc; // WndProc handles messages
+ wc.cbClsExtra = 0; // no extra window data
+ wc.cbWndExtra = 0; // no extra window data
+ wc.hInstance = g_hInstance; // set the instance
+ wc.hIcon = LoadIcon(NULL, IDI_WINLOGO); // load the default icon
+ wc.hCursor = LoadCursor(NULL, IDC_ARROW); // load the arrow pointer
+ wc.hbrBackground = NULL; // no background required for GL
+ wc.lpszMenuName = NULL; // we don't want a menu
+ wc.lpszClassName = L"OpenGL"; // set the class name
+
+ // attempt to register the window class
+ if (!RegisterClass(&wc))
+ {
+ MessageBox(NULL,L"Failed to register the window class.",L"ERROR",MB_OK|MB_ICONEXCLAMATION);
+ return FALSE; // Return FALSE
+ }
+ dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
+ dwStyle = WS_OVERLAPPEDWINDOW;
+
+ // adjust window to true requested size
+ AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle);
+
+ // create the window
+ g_hWnd = CreateWindowEx(dwExStyle, // extended style for the window
+ L"OpenGL", // class name
+ title, // window title
+ dwStyle | // defined window style
+ WS_CLIPSIBLINGS | // required window style
+ WS_CLIPCHILDREN, // required window style
+ 0, 0, // window position
+ WindowRect.right-WindowRect.left, // calculate window width
+ WindowRect.bottom-WindowRect.top, // calculate window height
+ NULL, // no parent window
+ NULL, // no menu
+ g_hInstance, // instance
+ NULL); // dont pass anything to WM_CREATE
+ if (!g_hWnd)
+ {
+ KillGLWindow();
+ MessageBox(NULL,L"Window creation error.",L"ERROR",MB_OK|MB_ICONEXCLAMATION);
+ return FALSE;
+ }
+
+ static PIXELFORMATDESCRIPTOR pfd =
+ {
+ sizeof(PIXELFORMATDESCRIPTOR), // size of this pixel format descriptor
+ 1, // version number
+ PFD_DRAW_TO_WINDOW | // format must support window
+ PFD_SUPPORT_OPENGL | // format must support OpenGL
+ PFD_DOUBLEBUFFER, // must support double buffering
+ PFD_TYPE_RGBA, // request an RGBA format
+ bpp, // select our color depth
+ 0, 0, 0, 0, 0, 0, // color bits ignored
+ 0, // no alpha buffer
+ 0, // shift bit ignored
+ 0, // no accumulation buffer
+ 0, 0, 0, 0, // accumulation bits ignored
+ 32, // 32bit z-buffer (depth buffer)
+ 0, // no stencil buffer
+ 0, // no auxiliary buffer
+ PFD_MAIN_PLANE, // main drawing layer
+ 0, // reserved
+ 0, 0, 0 // layer masks ignored
+ };
+
+ // did we get a device context?
+ g_hDC = GetDC(g_hWnd);
+ if (!g_hDC)
+ {
+ KillGLWindow();
+ MessageBox(NULL,L"Can't create a GL device context.",L"ERROR",MB_OK|MB_ICONEXCLAMATION);
+ return FALSE;
+ }
+
+ // did windows find a matching pixel format?
+ PixelFormat = ChoosePixelFormat(g_hDC,&pfd);
+ if (!PixelFormat)
+ {
+ KillGLWindow();
+ MessageBox(NULL,L"Can't find a suitable pixelformat.",L"ERROR",MB_OK|MB_ICONEXCLAMATION);
+ return FALSE;
+ }
+
+ // are we able to set the pixel format?
+ if(!SetPixelFormat(g_hDC,PixelFormat,&pfd))
+ {
+ KillGLWindow();
+ MessageBox(NULL,L"Can't set the pixelformat.",L"ERROR",MB_OK|MB_ICONEXCLAMATION);
+ return FALSE;
+ }
+
+ // are we able to get a rendering context?
+ g_hRC=wglCreateContext(g_hDC);
+ if (!g_hRC)
+ {
+ KillGLWindow();
+ MessageBox(NULL,L"Can't create a GL rendering context.",L"ERROR",MB_OK|MB_ICONEXCLAMATION);
+ return FALSE;
+ }
+
+ // try to activate the rendering context
+ if(!wglMakeCurrent(g_hDC,g_hRC))
+ {
+ KillGLWindow();
+ MessageBox(NULL,L"Can't activate the GL rendering context.",L"ERROR",MB_OK|MB_ICONEXCLAMATION);
+ return FALSE;
+ }
+
+ ShowWindow(g_hWnd,SW_SHOW);
+ SetForegroundWindow(g_hWnd);
+ SetFocus(g_hWnd);
+ return TRUE;
+}
+
+
+int main(void)
+{
+ gfsdk_waveworks_result res;
+ if(!CreateGLWindow(L"sample_opengl", 1280, 720, 32))
+ {
+ return 0;
+ }
+
+ PrintGLInfo();
+
+ // Creating OceanSurface instance
+
+ g_ocean_simulation_settings.fft_period = 1000.0f;
+ g_ocean_simulation_settings.detail_level = (GFSDK_WaveWorks_Simulation_DetailLevel)g_max_detail_level;
+ g_ocean_simulation_settings.readback_displacements = false;
+ g_ocean_simulation_settings.num_readback_FIFO_entries = 0;
+ g_ocean_simulation_settings.aniso_level = 4;
+ g_ocean_simulation_settings.CPU_simulation_threading_model = GFSDK_WaveWorks_Simulation_CPU_Threading_Model_Automatic;
+ g_ocean_simulation_settings.use_Beaufort_scale = true;
+ g_ocean_simulation_settings.num_GPUs = 1;
+ g_ocean_simulation_settings.use_texture_arrays = true;
+ g_ocean_simulation_settings.enable_CUDA_timers = true;
+
+ g_pOceanSurf = new OceanSurface(g_ocean_simulation_settings.use_texture_arrays);
+
+ // Initializing GL functions to be passed to WaveWorks, in alphabetic order
+ g_GLFunctions.glGetError = g_pOceanSurf->glGetError;
+ g_GLFunctions.glGetIntegerv = g_pOceanSurf->glGetIntegerv;
+ g_GLFunctions.glTexParameterf = g_pOceanSurf->glTexParameterf;
+ g_GLFunctions.glTexParameteri = g_pOceanSurf->glTexParameteri;
+ g_GLFunctions.glTexImage2D = g_pOceanSurf->glTexImage2D;
+ g_GLFunctions.glTexSubImage2D = g_pOceanSurf->glTexSubImage2D;
+ g_GLFunctions.glClear = g_pOceanSurf->glClear;
+ g_GLFunctions.glClearColor = g_pOceanSurf->glClearColor;
+ g_GLFunctions.glColorMask = g_pOceanSurf->glColorMask;
+ g_GLFunctions.glDisable = g_pOceanSurf->glDisable;
+ g_GLFunctions.glViewport = g_pOceanSurf->glViewport;
+ g_GLFunctions.glBindTexture = g_pOceanSurf->glBindTexture;
+ g_GLFunctions.glDeleteTextures = g_pOceanSurf->glDeleteTextures;
+ g_GLFunctions.glGenTextures = g_pOceanSurf->glGenTextures;
+ g_GLFunctions.glDrawElements = g_pOceanSurf->glDrawElements;
+ g_GLFunctions.glActiveTexture = g_pOceanSurf->glActiveTexture;
+ g_GLFunctions.glBindBuffer = g_pOceanSurf->glBindBuffer;
+ g_GLFunctions.glDeleteBuffers = g_pOceanSurf->glDeleteBuffers;
+ g_GLFunctions.glGenBuffers = g_pOceanSurf->glGenBuffers;
+ g_GLFunctions.glBufferData = g_pOceanSurf->glBufferData;
+ g_GLFunctions.glMapBufferRange = g_pOceanSurf->glMapBufferRange;
+ g_GLFunctions.glUnmapBuffer = g_pOceanSurf->glUnmapBuffer;
+ g_GLFunctions.glAttachShader = g_pOceanSurf->glAttachShader;
+ g_GLFunctions.glCompileShader = g_pOceanSurf->glCompileShader;
+ g_GLFunctions.glCreateProgram = g_pOceanSurf->glCreateProgram;
+ g_GLFunctions.glCreateShader = g_pOceanSurf->glCreateShader;
+ g_GLFunctions.glDeleteProgram = g_pOceanSurf->glDeleteProgram;
+ g_GLFunctions.glDeleteShader = g_pOceanSurf->glDeleteShader;
+ g_GLFunctions.glDisableVertexAttribArray = g_pOceanSurf->glDisableVertexAttribArray;
+ g_GLFunctions.glEnableVertexAttribArray = g_pOceanSurf->glEnableVertexAttribArray;
+ g_GLFunctions.glGetAttribLocation = g_pOceanSurf->glGetAttribLocation;
+ g_GLFunctions.glGetProgramiv = g_pOceanSurf->glGetProgramiv;
+ g_GLFunctions.glGetProgramInfoLog = g_pOceanSurf->glGetProgramInfoLog;
+ g_GLFunctions.glGetShaderiv = g_pOceanSurf->glGetShaderiv;
+ g_GLFunctions.glGetShaderInfoLog = g_pOceanSurf->glGetShaderInfoLog;
+ g_GLFunctions.glGetUniformLocation = g_pOceanSurf->glGetUniformLocation;
+ g_GLFunctions.glLinkProgram = g_pOceanSurf->glLinkProgram;
+ g_GLFunctions.glShaderSource = g_pOceanSurf->glShaderSource;
+ g_GLFunctions.glUseProgram = g_pOceanSurf->glUseProgram;
+ g_GLFunctions.glUniform1f = g_pOceanSurf->glUniform1f;
+ g_GLFunctions.glUniform1i = g_pOceanSurf->glUniform1i;
+ g_GLFunctions.glUniform3fv = g_pOceanSurf->glUniform3fv;
+ g_GLFunctions.glUniform4fv = g_pOceanSurf->glUniform4fv;
+ g_GLFunctions.glVertexAttribPointer = g_pOceanSurf->glVertexAttribPointer;
+ g_GLFunctions.glUniformMatrix3x4fv = g_pOceanSurf->glUniformMatrix3x4fv;
+ g_GLFunctions.glBindFramebuffer = g_pOceanSurf->glBindFramebuffer;
+ g_GLFunctions.glDeleteFramebuffers = g_pOceanSurf->glDeleteFramebuffers;
+ g_GLFunctions.glGenFramebuffers = g_pOceanSurf->glGenFramebuffers;
+ g_GLFunctions.glCheckFramebufferStatus = g_pOceanSurf->glCheckFramebufferStatus;
+ g_GLFunctions.glGenerateMipmap = g_pOceanSurf->glGenerateMipmap;
+ g_GLFunctions.glFramebufferTexture2D = g_pOceanSurf->glFramebufferTexture2D;
+ g_GLFunctions.glPatchParameteri = g_pOceanSurf->glPatchParameteri;
+ g_GLFunctions.glGenQueries = g_pOceanSurf->glGenQueries;
+ g_GLFunctions.glDeleteQueries = g_pOceanSurf->glDeleteQueries;
+ g_GLFunctions.glQueryCounter = g_pOceanSurf->glQueryCounter;
+ g_GLFunctions.glGetQueryObjectui64v = g_pOceanSurf->glGetQueryObjectui64v;
+ g_GLFunctions.glGetActiveAttrib = g_pOceanSurf->glGetActiveAttrib;
+ g_GLFunctions.glFramebufferTextureLayer = g_pOceanSurf->glFramebufferTextureLayer;
+ g_GLFunctions.glBlitFramebuffer = g_pOceanSurf->glBlitFramebuffer;
+ g_GLFunctions.glTexImage3D = g_pOceanSurf->glTexImage3D;
+ g_GLFunctions.glReadBuffer = g_pOceanSurf->glReadBuffer;
+ g_GLFunctions.glDrawBuffers = g_pOceanSurf->glDrawBuffers;
+
+
+ // initializing WaveWorks
+ fprintf(stdout, "\nInitializing:\n");
+ res = GFSDK_WaveWorks_InitGL2(&g_GLFunctions, NULL, GFSDK_WAVEWORKS_API_GUID);
+ if(res == gfsdk_waveworks_result_OK)
+ {
+ fprintf(stdout, "GFSDK_WaveWorks_InitGL2: OK\n");
+ }
+ else
+ {
+ fprintf(stdout, "GFSDK_WaveWorks_InitGL2 ERROR: %i, exiting..\n", res);
+ return res;
+ }
+
+ // initializing QuadTree
+ g_ocean_param_quadtree.min_patch_length = 40.0f;
+ g_ocean_param_quadtree.upper_grid_coverage = 64.0f;
+ g_ocean_param_quadtree.mesh_dim = 128;
+ g_ocean_param_quadtree.sea_level = 0.f;
+ g_ocean_param_quadtree.auto_root_lod = 10;
+ g_ocean_param_quadtree.tessellation_lod = 100.0f;
+ g_ocean_param_quadtree.geomorphing_degree = 1.f;
+ g_ocean_param_quadtree.enable_CPU_timers = true;
+ res = g_pOceanSurf->InitQuadTree(g_ocean_param_quadtree);
+ if(res == gfsdk_waveworks_result_OK)
+ {
+ fprintf(stdout, "InitQuadTree: OK\n");
+ }
+ else
+ {
+ fprintf(stdout, "InitQuadTree ERROR: %i, exiting..\n", res);
+ return res;
+ }
+
+ // checking available detail level
+ int detail_level = 0;
+ for(; detail_level != Num_GFSDK_WaveWorks_Simulation_DetailLevels; ++detail_level) {
+ if(!GFSDK_WaveWorks_Simulation_DetailLevelIsSupported_GL2((GFSDK_WaveWorks_Simulation_DetailLevel)detail_level))
+ break;
+ }
+ if(0 == detail_level)
+ return false;
+ g_max_detail_level = (GFSDK_WaveWorks_Simulation_DetailLevel)(detail_level - 1);
+
+ // initializing simulation
+ g_ocean_simulation_param.time_scale = 0.5f;
+ g_ocean_simulation_param.wave_amplitude = 1.0f;
+ g_ocean_simulation_param.wind_dir.x = 0.8f;
+ g_ocean_simulation_param.wind_dir.y = 0.6f;
+ g_ocean_simulation_param.wind_speed = 9.0f;
+ g_ocean_simulation_param.wind_dependency = 0.98f;
+ g_ocean_simulation_param.choppy_scale = 1.f;
+ g_ocean_simulation_param.small_wave_fraction = 0.f;
+ g_ocean_simulation_param.foam_dissipation_speed = 0.6f;
+ g_ocean_simulation_param.foam_falloff_speed = 0.985f;
+ g_ocean_simulation_param.foam_generation_amount = 0.12f;
+ g_ocean_simulation_param.foam_generation_threshold = 0.37f;
+
+ res = GFSDK_WaveWorks_Simulation_CreateGL2(g_ocean_simulation_settings, g_ocean_simulation_param, (void*) g_hRC, &g_hOceanSimulation);
+ if(res == gfsdk_waveworks_result_OK)
+ {
+ fprintf(stdout, "GFSDK_WaveWorks_Simulation_CreateGL2: OK\n");
+ }
+ else
+ {
+ fprintf(stdout, "GFSDK_WaveWorks_Simulation_CreateGL2 ERROR: %i, exiting..\n", res);
+ return res;
+ }
+ GFSDK_WaveWorks_Simulation_UpdateProperties(g_hOceanSimulation, g_ocean_simulation_settings, g_ocean_simulation_param);
+ GFSDK_WaveWorks_Quadtree_SetFrustumCullMargin(g_pOceanSurf->hOceanQuadTree, GFSDK_WaveWorks_Simulation_GetConservativeMaxDisplacementEstimate(g_hOceanSimulation));
+
+ // initializing AntTweakBars
+ if(TwInit(TW_OPENGL, NULL)==0)
+ {
+ fprintf (stdout, "Error initializing AntTweakBar library, exiting..\n");
+ // Cleanup WaveWorks
+ delete g_pOceanSurf;
+ GFSDK_WaveWorks_Simulation_Destroy(g_hOceanSimulation);
+ GFSDK_WaveWorks_ReleaseGL2();
+
+ // shutting down
+ KillGLWindow();
+ return -1;
+ }
+ TwWindowSize(1280, 720);
+
+ // Status bar
+ g_pStatsBar = TwNewBar("Stats");
+ TwDefine(" Stats help='Times listed in Stats are Milliseconds'");
+ TwDefine(" Stats size='400 200'");
+ TwDefine(" Stats position='10 10'");
+ TwDefine(" Stats alpha=0");
+ TwDefine(" Stats movable=false");
+ TwDefine(" Stats iconifiable=false");
+ TwDefine(" Stats resizable=false");
+ TwDefine(" Stats refresh=0.1");
+ TwDefine(" Stats visible=false");
+ TwAddVarRO(g_pStatsBar, "Frames Per Second", TW_TYPE_INT32, &g_FPS, "");
+ TwAddVarRO(g_pStatsBar, "Quadtree Patches Drawn", TW_TYPE_INT32, &g_ocean_stats_quadtree.num_patches_drawn, "");
+ TwAddSeparator(g_pStatsBar, NULL, NULL);
+ TwAddVarRO(g_pStatsBar, "CPU: Main Thread Wait Time", TW_TYPE_FLOAT, &g_ocean_stats_simulation_filtered.CPU_main_thread_wait_time, "precision=2");
+ TwAddVarRO(g_pStatsBar, "CPU: Threads Start To Finish Time", TW_TYPE_FLOAT, &g_ocean_stats_simulation_filtered.CPU_threads_start_to_finish_time, "precision=2");
+ TwAddVarRO(g_pStatsBar, "CPU: Threads Total Time", TW_TYPE_FLOAT, &g_ocean_stats_simulation_filtered.CPU_threads_total_time, "precision=2");
+ TwAddVarRO(g_pStatsBar, "GPU: FFT Simulation Time", TW_TYPE_FLOAT, &g_ocean_stats_simulation_filtered.GPU_FFT_simulation_time, "precision=2");
+ TwAddVarRO(g_pStatsBar, "GPU: GFX Time", TW_TYPE_FLOAT, &g_ocean_stats_simulation_filtered.GPU_gfx_time, "precision=2");
+ TwAddVarRO(g_pStatsBar, "GPU: Simulation Time", TW_TYPE_FLOAT, &g_ocean_stats_simulation_filtered.GPU_simulation_time, "precision=2");
+ TwAddVarRO(g_pStatsBar, "CPU: Update Time", TW_TYPE_FLOAT, &g_ocean_stats_simulation_filtered.GPU_update_time, "precision=2");
+
+ // Controls bar
+ g_pControlsBar = TwNewBar("Controls");
+ TwDefine(" Controls size='300 700'");
+ TwDefine(" Controls position='970 10'");
+ TwDefine(" Controls alpha=0");
+ TwDefine(" Controls movable=false");
+ TwDefine(" Controls iconifiable=false");
+ TwDefine(" Controls resizable=false");
+ TwDefine(" Controls valueswidth=100");
+ TwAddVarRW(g_pControlsBar, "Wireframe", TW_TYPE_BOOLCPP, &g_Wireframe, NULL);
+ TwAddVarRW(g_pControlsBar, "Simulate Water", TW_TYPE_BOOLCPP, &g_SimulateWater, NULL);
+ TwAddVarCB(g_pControlsBar, "Show Stats", TW_TYPE_BOOLCPP, CB_SetShowStats, CB_GetShowStats, &g_ShowStats, NULL);
+ TwAddSeparator(g_pControlsBar, NULL, NULL);
+ TwAddVarCB(g_pControlsBar, "Use Beaufort Presets", TW_TYPE_BOOLCPP, CB_SetUseBeaufort, CB_GetUseBeaufort, &g_ocean_simulation_settings.use_Beaufort_scale, NULL);
+ TwAddVarCB(g_pControlsBar, "Wave Amplitude", TW_TYPE_FLOAT, CB_SetWaveAmplitude, CB_GetWaveAmplitude, &g_ocean_simulation_param.wave_amplitude, "min=0 max=2 step=0.1 precision=1 visible=false");
+ TwAddVarCB(g_pControlsBar, "Chop Scale", TW_TYPE_FLOAT, CB_SetChopScale, CB_GetChopScale, &g_ocean_simulation_param.choppy_scale, "min=0 max=1 step=0.1 precision=1 visible=false");
+ TwAddVarCB(g_pControlsBar, "Wind Speed", TW_TYPE_FLOAT, CB_SetWindSpeed, CB_GetWindSpeed, &g_ocean_simulation_param.wind_speed, "min=0 max = 12 step=0.1 precision=1");
+ TwAddVarCB(g_pControlsBar, "Wind Dependency", TW_TYPE_FLOAT, CB_SetWindDependency, CB_GetWindDependency, &g_ocean_simulation_param.wind_dependency, "min=0 max=1 step=0.1 precision=1");
+ TwAddVarCB(g_pControlsBar, "Time Scale", TW_TYPE_FLOAT, CB_SetTimeScale, CB_GetTimeScale, &g_ocean_simulation_param.time_scale, "min=0.1 max=2 step=0.1 precision=1");
+ TwAddVarCB(g_pControlsBar, "Aniso Level", TW_TYPE_INT8, CB_SetAnisoLevel, CB_GetAnisoLevel, &g_ocean_simulation_settings.aniso_level, "min=1 max=16 step=1");
+ TwAddSeparator(g_pControlsBar, NULL, NULL);
+ TwEnumVal QualityEV[] = { {GFSDK_WaveWorks_Simulation_DetailLevel_Normal, "Normal"}, {GFSDK_WaveWorks_Simulation_DetailLevel_High, "High"}, {GFSDK_WaveWorks_Simulation_DetailLevel_Extreme, "Extreme"}};
+ TwType qualityType;
+ qualityType = TwDefineEnum("Simulation Detail Level", QualityEV, 3);
+ TwAddVarCB(g_pControlsBar, "Simulation Detail Level", qualityType, CB_SetDetailLevel, CB_GetDetailLevel, &g_ocean_simulation_settings.detail_level, NULL);
+
+ fprintf(stdout, "Entering main loop\n", res);
+
+ // entering main loop
+ while(!g_ExitApp)
+ {
+ if (PeekMessage(&g_Msg,NULL,0,0,PM_REMOVE))
+ {
+ if (g_Msg.message==WM_QUIT)
+ {
+ g_ExitApp=TRUE;
+ }
+ else
+ {
+ TranslateMessage(&g_Msg);
+ DispatchMessage(&g_Msg);
+ }
+ }
+ else
+ {
+ // draw the scene if there are no messages
+ if (g_WindowActive)
+ {
+ if (g_PressedKeys[VK_ESCAPE])
+ {
+ g_ExitApp = TRUE;
+ }
+ else
+ {
+ ProcessWSADKeys();
+ RenderFrame();
+ // updating stats string for Stats AntTweakBar
+
+ }
+ }
+ }
+ }
+
+ // Cleanup AntTweakBars
+ TwTerminate();
+
+ // Cleanup WaveWorks
+ delete g_pOceanSurf;
+ GFSDK_WaveWorks_Simulation_Destroy(g_hOceanSimulation);
+ GFSDK_WaveWorks_ReleaseGL2();
+
+ // shutting down
+ KillGLWindow();
+ return (int)g_Msg.wParam;
+}
+
+
+// message processing function
+LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+
+ // pass messages to AntTweakBars
+ if( TwEventWin(hWnd, uMsg, wParam, lParam) ) // send event message to AntTweakBar
+ return 0; // event has been handled by AntTweakBar
+
+ switch (uMsg)
+ {
+ case WM_ACTIVATE: // watch for window activate message
+ {
+ if (!HIWORD(wParam)) // check minimization state
+ {
+ g_WindowActive = TRUE; // program is active
+ }
+ else
+ {
+ g_WindowActive = FALSE; // program is no longer active
+ }
+ return 0; // return to the message loop
+ }
+
+ case WM_SYSCOMMAND:
+ {
+ switch (wParam)
+ {
+ case SC_SCREENSAVE: // screensaver trying to start?
+ case SC_MONITORPOWER: // monitor trying to enter powersave?
+ return 0; // prevent from happening
+ }
+ break;
+ }
+
+ case WM_CLOSE:
+ {
+ g_ExitApp = true;
+ PostQuitMessage(0);
+ return 0;
+ }
+
+ case WM_KEYDOWN:
+ {
+ g_PressedKeys[wParam] = TRUE;
+ switch(wParam)
+ {
+ case 219: // "["
+ g_ocean_simulation_settings.detail_level = GFSDK_WaveWorks_Simulation_DetailLevel((g_ocean_simulation_settings.detail_level + g_max_detail_level) % (g_max_detail_level+1));
+ GFSDK_WaveWorks_Simulation_UpdateProperties(g_hOceanSimulation, g_ocean_simulation_settings, g_ocean_simulation_param);
+ GFSDK_WaveWorks_Quadtree_SetFrustumCullMargin(g_pOceanSurf->hOceanQuadTree, GFSDK_WaveWorks_Simulation_GetConservativeMaxDisplacementEstimate(g_hOceanSimulation));
+ break;
+ case 221: // "]"
+ g_ocean_simulation_settings.detail_level = GFSDK_WaveWorks_Simulation_DetailLevel((g_ocean_simulation_settings.detail_level + 1) % (g_max_detail_level+1));
+ GFSDK_WaveWorks_Simulation_UpdateProperties(g_hOceanSimulation, g_ocean_simulation_settings, g_ocean_simulation_param);
+ GFSDK_WaveWorks_Quadtree_SetFrustumCullMargin(g_pOceanSurf->hOceanQuadTree, GFSDK_WaveWorks_Simulation_GetConservativeMaxDisplacementEstimate(g_hOceanSimulation));
+ break;
+ default:
+ break;
+ }
+ return 0;
+ }
+
+ case WM_KEYUP:
+ {
+ g_PressedKeys[wParam] = FALSE;
+ return 0;
+ }
+
+ case WM_SIZE:
+ {
+ if(g_pOceanSurf)
+ {
+ g_pOceanSurf->ScreenWidth = LOWORD(lParam);
+ g_pOceanSurf->ScreenHeight = HIWORD(lParam);
+ TwWindowSize(g_pOceanSurf->ScreenWidth, g_pOceanSurf->ScreenHeight);
+ int pos[2] = {g_pOceanSurf->ScreenWidth - 300 - 10, 10};
+ int size[2] = {300, g_pOceanSurf->ScreenHeight - 20};
+ TwSetParam(g_pControlsBar,NULL,"position",TW_PARAM_INT32, 2, &pos);
+ TwSetParam(g_pControlsBar,NULL,"size",TW_PARAM_INT32, 2, &size);
+ }
+ return 0;
+ }
+
+ case WM_MOUSEMOVE:
+ {
+ ProcessMouseMotion(LOWORD(lParam), HIWORD(lParam), (wParam & MK_LBUTTON) > 0? true:false);
+ }
+ }
+
+ // pass all remaining messages to DefWindowProc
+ return DefWindowProc(hWnd,uMsg,wParam,lParam);
+}
diff --git a/sample/opengl/water.glsl b/sample/opengl/water.glsl
new file mode 100644
index 0000000..5dc2cf4
--- /dev/null
+++ b/sample/opengl/water.glsl
@@ -0,0 +1,170 @@
+<<<VSTEXT>>>
+#version 420 core
+
+#define GFSDK_WAVEWORKS_GL
+
+#define GFSDK_WAVEWORKS_DECLARE_GEOM_VS_CONSTANT(Type,Label,Regoff) uniform Type Label;
+#include "GFSDK_WaveWorks_Quadtree.fxh"
+
+#define GFSDK_WAVEWORKS_DECLARE_ATTR_VS_CONSTANT(Type,Label,Regoff) uniform Type Label;
+#define GFSDK_WAVEWORKS_DECLARE_ATTR_VS_SAMPLER(Label,TextureLabel,Regoff) uniform sampler2D Label;
+#define GFSDK_WAVEWORKS_DECLARE_ATTR_VS_SAMPLER_TEXTUREARRAY(Label,TextureLabel,Regoff) uniform sampler2DArray Label;
+#define GFSDK_WAVEWORKS_DECLARE_ATTR_PS_CONSTANT(Type,Label,Regoff) uniform Type Label;
+#define GFSDK_WAVEWORKS_DECLARE_ATTR_PS_SAMPLER(Label,TextureLabel,Regoff) uniform sampler2D Label;
+#define GFSDK_WAVEWORKS_DECLARE_ATTR_PS_SAMPLER_TEXTUREARRAY(Label,TextureLabel,Regoff) uniform sampler2DArray Label;
+#include "GFSDK_WaveWorks_Attributes.fxh"
+
+// User uniforms
+uniform mat4x4 u_ViewProjMatrix;
+
+struct VSInputStruct
+{
+ GFSDK_WAVEWORKS_VERTEX_INPUT WaveWorksInput;
+};
+
+in VSInputStruct VSInput;
+out GFSDK_WAVEWORKS_VERTEX_OUTPUT VSOutput;
+
+void main()
+{
+ VSOutput = GFSDK_WaveWorks_GetDisplacedVertex(VSInput.WaveWorksInput);
+ vec3 dwpos = VSOutput.pos_world;
+ gl_Position = u_ViewProjMatrix*vec4(dwpos,1.f);
+}
+
+
+<<<FSTEXT>>>
+#version 420 core
+
+#define GFSDK_WAVEWORKS_GL
+
+#define GFSDK_WAVEWORKS_DECLARE_GEOM_VS_CONSTANT(Type,Label,Regoff) uniform Type Label;
+#include "GFSDK_WaveWorks_Quadtree.fxh"
+
+#define GFSDK_WAVEWORKS_DECLARE_ATTR_VS_CONSTANT(Type,Label,Regoff) uniform Type Label;
+#define GFSDK_WAVEWORKS_DECLARE_ATTR_VS_SAMPLER(Label,TextureLabel,Regoff) uniform sampler2D Label;
+#define GFSDK_WAVEWORKS_DECLARE_ATTR_VS_SAMPLER_TEXTUREARRAY(Label,TextureLabel,Regoff) uniform sampler2DArray Label;
+#define GFSDK_WAVEWORKS_DECLARE_ATTR_PS_CONSTANT(Type,Label,Regoff) uniform Type Label;
+#define GFSDK_WAVEWORKS_DECLARE_ATTR_PS_SAMPLER(Label,TextureLabel,Regoff) uniform sampler2D Label;
+#define GFSDK_WAVEWORKS_DECLARE_ATTR_PS_SAMPLER_TEXTUREARRAY(Label,TextureLabel,Regoff) uniform sampler2DArray Label;
+#include "GFSDK_WaveWorks_Attributes.fxh"
+
+// User uniforms
+uniform sampler2D g_texFoamIntensityMap;
+uniform sampler2D g_texFoamDiffuseMap;
+
+// User local variables
+vec3 g_SkyColor = {0.38, 0.45, 0.56};
+vec3 g_BendParam = {0.1, -0.4, 0.2};
+
+vec3 g_SunDir = {0.936016, -0.343206, 0.0780013};
+vec3 g_WaterDeepColor={0.0,0.4,0.6};
+vec3 g_WaterScatterColor={0.0,0.7,0.6};
+vec2 g_WaterColorIntensity={0.2,0.1};
+
+vec3 g_FoamColor = {0.90, 0.95, 1.0};
+vec3 g_FoamUnderwaterColor = {0.90, 0.95, 1.0};
+
+// in & out variables
+in GFSDK_WAVEWORKS_VERTEX_OUTPUT VSOutput;
+
+out vec4 color;
+
+void main()
+{
+
+ GFSDK_WAVEWORKS_SURFACE_ATTRIBUTES surface_attributes = GFSDK_WaveWorks_GetSurfaceAttributes(VSOutput.interp);
+
+ float fresnel_factor;
+ float diffuse_factor;
+ float specular_factor;
+ float scatter_factor;
+
+ vec3 pixel_to_light_vector=g_SunDir;
+ vec3 pixel_to_eye_vector=surface_attributes.eye_dir;
+ vec3 reflected_eye_to_pixel_vector = reflect(-surface_attributes.eye_dir, surface_attributes.normal);
+
+ // simulating scattering/double refraction: light hits the side of wave, travels some distance in water, and leaves wave on the other side
+ // it's difficult to do it physically correct without photon mapping/ray tracing, so using simple but plausible emulation below
+
+ // only the crests of water waves generate double refracted light
+ scatter_factor=1.0*max(0,VSOutput.world_displacement.z*0.001+0.3);
+
+
+ // the waves that lie between camera and light projection on water plane generate maximal amount of double refracted light
+ scatter_factor*=pow(max(0.0,dot(normalize(vec3(pixel_to_light_vector.x,0.0,pixel_to_light_vector.z)),-pixel_to_eye_vector)),2.0);
+
+ // the slopes of waves that are oriented back to light generate maximal amount of double refracted light
+ scatter_factor*=pow(max(0.0,0.5-0.5*dot(pixel_to_light_vector,surface_attributes.normal)),3.0);
+
+
+ // water crests gather more light than lobes, so more light is scattered under the crests
+ scatter_factor+=2.0*g_WaterColorIntensity.y*max(0,VSOutput.world_displacement.z*0.001+0.3)*
+ // the scattered light is best seen if observing direction is normal to slope surface
+ max(0,dot(pixel_to_eye_vector,surface_attributes.normal));
+
+
+ // calculating fresnel factor
+ float r=(1.0 - 1.13)*(1.0 - 1.13)/(1.0 + 1.13);
+ fresnel_factor = r + (1.0-r)*pow(saturate(1.0 - dot(surface_attributes.normal,pixel_to_eye_vector)),4.0);
+
+ // calculating diffuse intensity of water surface itself
+ diffuse_factor=g_WaterColorIntensity.x+g_WaterColorIntensity.y*max(0,dot(pixel_to_light_vector,surface_attributes.normal));
+
+ vec3 refraction_color=diffuse_factor*g_WaterDeepColor;
+
+ // adding color that provide foam bubbles spread in water
+ refraction_color += g_FoamUnderwaterColor*saturate(surface_attributes.foam_turbulent_energy*0.2);
+
+ // adding scatter light component
+ refraction_color+=g_WaterScatterColor*scatter_factor;
+
+ // reflection color
+ vec3 reflection_color = g_SkyColor;
+
+ // fading reflection color to half if reflected vector points below water surface
+ reflection_color.rgb *= 1.0 - 0.5*max(0.0,min(1.0,-reflected_eye_to_pixel_vector.z*4.0));
+
+ // applying Fresnel law
+ vec3 water_color = mix(refraction_color,reflection_color,fresnel_factor);
+
+ // applying surface foam provided by turbulent energy
+
+ // low frequency foam map
+ float foam_intensity_map_lf = 1.0*texture(g_texFoamIntensityMap, VSOutput.pos_world_undisplaced.xy*0.04*vec2(1,1)).x - 1.0;
+
+ // high frequency foam map
+ float foam_intensity_map_hf = 1.0*texture(g_texFoamIntensityMap, VSOutput.pos_world_undisplaced.xy*0.15*vec2(1,1)).x - 1.0;
+
+ // ultra high frequency foam map
+ float foam_intensity_map_uhf = 1.0*texture(g_texFoamIntensityMap, VSOutput.pos_world_undisplaced.xy*0.3*vec2(1,1)).x;
+
+ float foam_intensity;
+ foam_intensity = saturate(foam_intensity_map_hf + min(3.5,1.0*surface_attributes.foam_turbulent_energy-0.2));
+ foam_intensity += (foam_intensity_map_lf + min(1.5,1.0*surface_attributes.foam_turbulent_energy));
+
+
+ foam_intensity -= 0.1*saturate(-surface_attributes.foam_surface_folding);
+
+ foam_intensity = max(0,foam_intensity);
+
+ foam_intensity *= 1.0+0.8*saturate(surface_attributes.foam_surface_folding);
+
+ float foam_bubbles = texture(g_texFoamDiffuseMap, VSOutput.pos_world_undisplaced.xy).r;
+ foam_bubbles = saturate(5.0*(foam_bubbles-0.8));
+
+ // applying foam hats
+ foam_intensity += max(0,foam_intensity_map_uhf*2.0*surface_attributes.foam_wave_hats);
+
+ foam_intensity = pow(foam_intensity, 0.7);
+ foam_intensity = saturate(foam_intensity*foam_bubbles*1.0);
+ //
+
+ // foam diffuse color
+ float foam_diffuse_factor=max(0,0.8+max(0,0.2*dot(pixel_to_light_vector,surface_attributes.normal)));
+
+ water_color = mix(water_color,foam_diffuse_factor*vec3(1.0,1.0,1.0),foam_intensity);
+
+ color = vec4(water_color,0);
+}
+