diff options
| author | Jason Maskell <[email protected]> | 2016-05-23 13:25:08 +0200 |
|---|---|---|
| committer | Jason Maskell <[email protected]> | 2016-05-23 13:25:08 +0200 |
| commit | 9eb5141c98951c36ed8561a0b0571c511a96ef95 (patch) | |
| tree | f536a91154df6b1b2bdaa3709a8bdd172c17769c | |
| parent | Moved media to a more central location. (diff) | |
| download | waveworks_archive-9eb5141c98951c36ed8561a0b0571c511a96ef95.tar.xz waveworks_archive-9eb5141c98951c36ed8561a0b0571c511a96ef95.zip | |
Added OpenGL sample - compiles and runs but doesn't work.
| -rw-r--r-- | CMakeLists.txt | 3 | ||||
| -rw-r--r-- | cmake/FindAntTweakBar.cmake | 40 | ||||
| -rw-r--r-- | compiler/cmake/sample_d3d11.cmake | 6 | ||||
| -rw-r--r-- | compiler/cmake/sample_opengl.cmake | 140 | ||||
| -rw-r--r-- | sample/opengl/math_code.cpp | 488 | ||||
| -rw-r--r-- | sample/opengl/math_code.h | 49 | ||||
| -rw-r--r-- | sample/opengl/ocean_surface.cpp | bin | 0 -> 64730 bytes | |||
| -rw-r--r-- | sample/opengl/ocean_surface.h | 345 | ||||
| -rw-r--r-- | sample/opengl/sample_opengl.cpp | 850 | ||||
| -rw-r--r-- | sample/opengl/water.glsl | 170 |
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 Binary files differnew file mode 100644 index 0000000..8542e01 --- /dev/null +++ b/sample/opengl/ocean_surface.cpp 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); +} + |