diff --git a/CMakeLists.txt b/CMakeLists.txt index d59ec4a..430aea5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,7 +22,8 @@ set_target_properties(fix::assimp PROPERTIES INTERFACE_LINK_LIBRARIES "${ASSIMP_LIBRARIES};pugixml" INTERFACE_LINK_DIRECTORIES "${ASSIMP_LIBRARY_DIRS}" ) -file(GLOB TERRAIN_SRC src/terrain/*.cpp) +file(GLOB TERRAIN_SRC ${CMAKE_SOURCE_DIR}/src/terrain/*.cpp) +file(GLOB WATER_SRC ${CMAKE_SOURCE_DIR}/water/*.cpp) # The COMPONENTS part checks that OGRE was built the way we need it # The CONFIG flag makes sure we get OGRE instead of OGRE-next @@ -50,9 +51,9 @@ target_link_libraries(0_Bootstrap OgreBites OgreBullet OgrePaging ${BULLET_DYNAM target_include_directories(0_Bootstrap PUBLIC OgreBites OgrePaging OgreBullet) add_dependencies(0_Bootstrap stage_files) -add_executable(GuiTest GuiTest.cpp ${TERRAIN_SRC}) -target_link_libraries(GuiTest OgreBites OgreBullet OgrePaging OgreTerrain ${OgreProcedural_LIBRARIES} ${BULLET_DYNAMICS_LIBRARY} ${BULLET_COLLISION_LIBRARY} ${BULLET_MATH_LIBRARY}) -target_include_directories(GuiTest PUBLIC OgreBites OgrePaging OgreBullet OgreTerrain ${OgreProcedural_INCLUDE_DIRS}) +add_executable(GuiTest GuiTest.cpp ${TERRAIN_SRC} ${WATER_SRC}) +target_link_libraries(GuiTest OgreBites OgreBullet OgrePaging OgreTerrain OgreMeshLodGenerator ${OgreProcedural_LIBRARIES} ${BULLET_DYNAMICS_LIBRARY} ${BULLET_COLLISION_LIBRARY} ${BULLET_MATH_LIBRARY}) +target_include_directories(GuiTest PUBLIC OgreBites OgrePaging OgreBullet OgreTerrain OgreMeshLodGenerator ${OgreProcedural_INCLUDE_DIRS}) add_dependencies(GuiTest stage_files import_buildings) add_executable(Procedural Procedural.cpp ${TERRAIN_SRC}) @@ -130,23 +131,35 @@ set(DEBUG_MATERIAL_SRC debug.program debug.vert ) +set(WATER_SRC + water.material + water.program + water.frag + water.vert + water.compositor + waves2.png +) +set(MATERIAL_FILES) +foreach(MATERIAL_FILE ${SKYBOX_SRC}) + list(APPEND MATERIAL_FILES skybox/${MATERIAL_FILE}) +endforeach() +foreach(MATERIAL_FILE ${DEBUG_MATERIAL_SRC}) + list(APPEND MATERIAL_FILES resources/debug/${MATERIAL_FILE}) +endforeach() +foreach(MATERIAL_FILE ${WATER_SRC}) + list(APPEND MATERIAL_FILES water/${MATERIAL_FILE}) +endforeach() + + set(MATERIALS_OUTPUT) -foreach(SKYBOX_FILE ${SKYBOX_SRC}) - set(OUTPUT_FILE ${CMAKE_BINARY_DIR}/skybox/${SKYBOX_FILE}) - set(INPUT_FILE ${CMAKE_SOURCE_DIR}/skybox/${SKYBOX_FILE}) - add_custom_command(OUTPUT ${OUTPUT_FILE} - COMMAND ${CMAKE_COMMAND} -E copy ${INPUT_FILE} ${OUTPUT_FILE} - DEPENDS ${INPUT_FILE}) - list(APPEND MATERIALS_OUTPUT ${OUTPUT_FILE}) -endforeach() -foreach(DEBUG_MATERIAL_FILE ${DEBUG_MATERIAL_SRC}) - set(OUTPUT_FILE ${CMAKE_BINARY_DIR}/resources/debug/${DEBUG_MATERIAL_FILE}) - set(INPUT_FILE ${CMAKE_SOURCE_DIR}/resources/debug/${DEBUG_MATERIAL_FILE}) - add_custom_command(OUTPUT ${OUTPUT_FILE} - COMMAND ${CMAKE_COMMAND} -E copy ${INPUT_FILE} ${OUTPUT_FILE} - DEPENDS ${INPUT_FILE}) - list(APPEND MATERIALS_OUTPUT ${OUTPUT_FILE}) +foreach(MATERIAL_FILE ${MATERIAL_FILES}) + set(OUTPUT_FILE ${CMAKE_BINARY_DIR}/${MATERIAL_FILE}) + set(INPUT_FILE ${CMAKE_SOURCE_DIR}/${MATERIAL_FILE}) + add_custom_command(OUTPUT ${OUTPUT_FILE} + COMMAND ${CMAKE_COMMAND} -E copy ${INPUT_FILE} ${OUTPUT_FILE} + DEPENDS ${INPUT_FILE}) + list(APPEND MATERIALS_OUTPUT ${OUTPUT_FILE}) endforeach() add_custom_command( diff --git a/GuiTest.cpp b/GuiTest.cpp index 6f64794..e2aa9cf 100644 --- a/GuiTest.cpp +++ b/GuiTest.cpp @@ -8,8 +8,10 @@ #include #include #include +#include #include "src/terrain/terrain.h" +#include "water/water.h" class App; class SkyRenderer : public Ogre::SceneManager::Listener { protected: @@ -244,9 +246,7 @@ public: class App : public OgreBites::ApplicationContext { std::unique_ptr mDynWorld; std::unique_ptr mDbgDraw; - Ogre::SceneNode *mCameraNode; - Ogre::SceneNode *mCameraPivot; - Ogre::SceneNode *mCameraGoal; + Ogre::SceneNode *mCameraNode, *mCameraPivot, *mCameraGoal; Ogre::Camera *mCamera; Ogre::Real mPivotPitch; Ogre::SceneManager *mScnMgr; @@ -256,6 +256,7 @@ class App : public OgreBites::ApplicationContext { TerrainSetup m_terrain; Ogre::Light *mSun; SkyBoxRenderer *sky; + Water m_water; // OgreBites::TrayManager *mTrayMgr; class KeyboardListener : public OgreBites::InputListener, public Ogre::FrameListener { @@ -409,7 +410,7 @@ public: // create the camera mCamera = mScnMgr->createCamera("fps_camera"); - mCamera->setNearClipDistance(0.1f); // specific to this sample + mCamera->setNearClipDistance(0.05f); mCamera->setAutoAspectRatio(true); mCameraNode->attachObject(mCamera); @@ -427,7 +428,7 @@ public: mCameraNode->setFixedYawAxis(true); // our model is quite small, so reduce the clipping planes mCamera->setNearClipDistance(0.1f); - mCamera->setFarClipDistance(700); + mCamera->setFarClipDistance(800); mPivotPitch = 0; // mKeyDirection = Ogre::Vector3::ZERO; @@ -534,12 +535,12 @@ public: // bound the zoom if (!(dist + distChange < 3 && distChange < 0) && - !(dist + distChange > 40 && distChange > 0)) + !(dist + distChange > 60 && distChange > 0)) mCameraGoal->translate(0, 0, distChange, Ogre::Node::TS_LOCAL); Ogre::Vector3 mh = mCameraGoal->_getDerivedPosition(); float h = m_terrain.get_height(mh); - if (h + 3 > mh.y) + if (h + 10 > mh.y) mCameraGoal->translate(0, 10.0f * deltaZoom, distChange, Ogre::Node::TS_LOCAL); } @@ -607,6 +608,7 @@ public: } void createContent() { + int i; m_edit_ui.init_glb_list(); m_edit_ui.initGui(); createSun(); @@ -625,7 +627,7 @@ public: uint8_t renderQueue = drawFirst ? Ogre::RENDER_QUEUE_SKIES_EARLY : Ogre::RENDER_QUEUE_SKIES_LATE; - sky->create("Skybox/Dynamic", 490, renderQueue, + sky->create("Skybox/Dynamic", 450, renderQueue, Ogre::Quaternion::IDENTITY, Ogre::ResourceGroupManager:: AUTODETECT_RESOURCE_GROUP_NAME); @@ -636,18 +638,8 @@ public: "Skybox/Dynamic", "General"); OgreAssert(m, "Sky box material not found."); m->load(); - Ogre::MeshManager::getSingleton().createPlane( - "water", - Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, - Ogre::Plane(Ogre::Vector3::UNIT_Y, 0), 100, 100, 100, - 100, true, 1, 100, 100, Ogre::Vector3::UNIT_Z); - - // create a floor entity, give it a material, and place it at the origin - Ogre::Entity *water = mScnMgr->createEntity("Water", "water"); - water->setMaterialName("Water"); - mScnMgr->getRootSceneNode() - ->createChildSceneNode("Water") - ->attachObject(water); + m_water.createWater(mCamera); + getRoot()->addFrameListener(&m_water); } void create_entity_node(const Ogre::String &name, int key) { diff --git a/resources.cfg b/resources.cfg index f44e23b..57be0a0 100644 --- a/resources.cfg +++ b/resources.cfg @@ -19,6 +19,7 @@ FileSystem=resources/terrain # samples which require them. [General] FileSystem=skybox +FileSystem=water FileSystem=resources/buildings FileSystem=resources/debug # PBR media must come before the scripts that reference it diff --git a/resources/debug/debug.program b/resources/debug/debug.program index 8819fe1..93c333e 100644 --- a/resources/debug/debug.program +++ b/resources/debug/debug.program @@ -13,7 +13,7 @@ vertex_program debug_vp glsl glsles glslang hlsl source debug.vert default_params { - param_named worldViewProj worldviewproj_matrix + param_named_auto worldViewProj worldviewproj_matrix } } diff --git a/src/terrain/terrain.cpp b/src/terrain/terrain.cpp index f50d373..1dab295 100644 --- a/src/terrain/terrain.cpp +++ b/src/terrain/terrain.cpp @@ -59,7 +59,7 @@ public: terrainGroup->defineTerrain(x, y, heightMap); OGRE_FREE(heightMap, MEMCATEGORY_GEOMETRY); #endif - terrainGroup->defineTerrain(x, y, -0.2f); + terrainGroup->defineTerrain(x, y, -10.0f); } }; diff --git a/water/water.compositor b/water/water.compositor new file mode 100644 index 0000000..41338dd --- /dev/null +++ b/water/water.compositor @@ -0,0 +1,23 @@ +compositor Fresnel +{ + technique + { + texture reflection 512 512 PF_BYTE_RGB + texture refraction 512 512 PF_BYTE_RGB + target reflection + { + visibility_mask 0x00F // SURFACE objects + input previous + } + target refraction + { + visibility_mask 0x0F0 // SUBMERGED objects + input previous + } + target_output + { + input previous + } + } +} + diff --git a/water/water.cpp b/water/water.cpp new file mode 100644 index 0000000..f319ab8 --- /dev/null +++ b/water/water.cpp @@ -0,0 +1,122 @@ +#include +#include +#include +#include +#include "water.h" + +static const uint32_t SUBMERGED_MASK = 0x0F0; +static const uint32_t SURFACE_MASK = 0x00F; +static const uint32_t WATER_MASK = 0xF00; +Water::Water() + : FrameListener() + , mWaterNode(nullptr) + , mScnMgr(nullptr) + , mCameraNode(nullptr) + , mWaterPlane(Ogre::Vector3::UNIT_Y, 0) +{ +} + +Water::~Water() +{ + if (mWaterNode) + mScnMgr->destroySceneNode(mWaterNode); +} + +void Water::createWater(Ogre::Camera *camera) +{ + int i; + float w = 400; + mCamera = camera; + mScnMgr = camera->getSceneManager(); + mCameraNode = camera->getParentSceneNode(); + Ogre::Viewport *viewport = camera->getViewport(); + mCameraPosition = mCameraNode->getPosition(); + auto compositor = Ogre::CompositorManager::getSingleton().addCompositor( + viewport, "Fresnel"); + Ogre::CompositorManager::getSingleton().setCompositorEnabled( + viewport, "Fresnel", true); + + // toggle reflection in camera + compositor->getRenderTarget("reflection")->addListener(this); + + Ogre::MeshPtr water_plane = + Ogre::MeshManager::getSingleton().createPlane( + "water", + Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, + mWaterPlane, w, w, 100, 100, true, 1, 100, 100, + Ogre::Vector3::UNIT_Z); + if (!Ogre::MeshLodGenerator::getSingletonPtr()) + new Ogre::MeshLodGenerator(); + + Ogre::LodConfig lod_config(water_plane); + lod_config.createGeneratedLodLevel(w, 0.5f); + lod_config.createGeneratedLodLevel(w * 2.0, 0.25f); + Ogre::MeshLodGenerator::getSingleton().generateLodLevels(lod_config); + + Ogre::Vector3 positions[] = { { 0, 0, -1 }, { 0, 0, 1 }, { -1, 0, 0 }, + { 1, 0, 0 }, { -1, 0, -1 }, { -1, 0, 1 }, + { 1, 0, -1 }, { 1, 0, 1 } }; + mWaterNode = mScnMgr->getRootSceneNode()->createChildSceneNode("Water"); + Ogre::Entity *water = mScnMgr->createEntity("WaterR", "water"); + water->setVisibilityFlags(WATER_MASK); + auto mat = Ogre::MaterialManager::getSingleton().getByName("Water"); + mat->getTechnique(0) + ->getPass(0) + ->getTextureUnitState(0) + ->setProjectiveTexturing(true, mCamera); + water->setMaterial(mat); + Ogre::SceneNode *node0 = mWaterNode->createChildSceneNode("WaterR"); + node0->attachObject(water); + for (i = 0; i < (int)sizeof(positions) / (int)sizeof(positions[0]); + i++) { + Ogre::Entity *water_lod1 = mScnMgr->createEntity( + "Water" + Ogre::StringConverter::toString(i), "water"); + water_lod1->setMaterialName("Water"); + Ogre::SceneNode *node_w = mWaterNode->createChildSceneNode( + "Water" + Ogre::StringConverter::toString(i), + positions[i] * w, Ogre::Quaternion::IDENTITY); + node_w->attachObject(water_lod1); + water_lod1->setVisibilityFlags(WATER_MASK); + } +} + +void Water::updateWater(float delta) +{ + if (mCameraPosition.squaredDistance(mCameraNode->getPosition()) > + 100.0f) { + mCameraPosition = mCameraNode->getPosition(); + Ogre::Vector3 waterPosition = mCameraPosition; + waterPosition.y = 0; + mWaterNode->setPosition(waterPosition); + } +} + +bool Water::frameEnded(const Ogre::FrameEvent &evt) +{ + updateWater(evt.timeSinceLastFrame); + return true; +} +bool Water::frameRenderingQueued(const Ogre::FrameEvent &evt) +{ + return FrameListener::frameRenderingQueued(evt); +} + +void Water::preRenderTargetUpdate(const Ogre::RenderTargetEvent &evt) +{ + mCamera->enableReflection(mWaterPlane); +} + +void Water::postRenderTargetUpdate(const Ogre::RenderTargetEvent &evt) +{ + mCamera->disableReflection(); +} + +void Water::add_submerged_entity(Ogre::Entity *ent) +{ + ent->setVisibilityFlags(SUBMERGED_MASK); +} + +void Water::add_surface_entity(Ogre::Entity *ent) +{ + ent->setVisibilityFlags(SURFACE_MASK); +} diff --git a/water/water.frag b/water/water.frag new file mode 100644 index 0000000..53ab117 --- /dev/null +++ b/water/water.frag @@ -0,0 +1,103 @@ +/*********************************************************************NVMH3**** +Copyright NVIDIA Corporation 2003 +TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THIS SOFTWARE IS PROVIDED +*AS IS* AND NVIDIA AND ITS SUPPLIERS DISCLAIM ALL WARRANTIES, EITHER EXPRESS +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL NVIDIA OR ITS SUPPLIERS +BE LIABLE FOR ANY SPECIAL, INCIDENTAL, INDIRECT, OR CONSEQUENTIAL DAMAGES +WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS, +BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR ANY OTHER PECUNIARY LOSS) +ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF NVIDIA HAS +BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + + +Comments: + Simple ocean shader with animated bump map and geometric waves + Based partly on "Effective Water Simulation From Physical Models", GPU Gems + +11 Aug 05: converted from HLSL to GLSL by Jeff Doyle (nfz) to work in Ogre +15 Jun 25: converted to OgreUnifiedShader.h by Sergey Lapin + +******************************************************************************/ + +OGRE_NATIVE_GLSL_VERSION_DIRECTIVE +#include + +SAMPLER2D(noiseMap, 0); +SAMPLER2D(reflectMap, 1); +SAMPLER2D(refractMap, 2); + +OGRE_UNIFORMS( + uniform vec4 ambient; + uniform vec4 diffuse; + uniform highp float time; + uniform vec4 deepColor; + uniform vec4 shallowColor; + uniform vec4 reflectionColor; + uniform float reflectionAmount; + uniform float reflectionBlur; + uniform float waterAmount; + uniform vec4 tintColour; + uniform float noiseScale; + uniform float fresnelScale; + uniform float fresnelPower; + uniform float fresnelBias; + uniform float hdrMultiplier; +) +MAIN_PARAMETERS +IN(mat3 rotMatrix, 17) // first row of the 3x3 transform from tangent to cube space +IN(vec2 bumpCoord0, 18) +IN(vec2 bumpCoord1, 19) +IN(vec2 bumpCoord2, 20) +IN(vec3 eyeVector, 21) +IN(vec3 noiseCoord, 22) +IN(highp vec4 projectionCoord, 23) +IN(vec3 eyeDir, 24) +IN(vec3 oNormal, 25) +MAIN_DECLARATION +{ +// vec4 t0 = texture2D(NormalMap, bumpCoord0) * 2.0 - 1.0; +// vec4 t1 = texture2D(NormalMap, bumpCoord1) * 2.0 - 1.0; +// vec4 t2 = texture2D(NormalMap, bumpCoord2) * 2.0 - 1.0; + vec4 t0 = normalize(vec4(0.1, 1, 0, 1)); + vec4 t1 = normalize(vec4(0, 1, 0.1, 1)); + vec4 t2 = normalize(vec4(-0.1, 1, 0.1, 1)); + // Do the tex projection manually so we can distort _after_ + vec2 final = projectionCoord.xy / projectionCoord.w; + + // Noise + vec3 noiseNormal = (texture2D(noiseMap, (noiseCoord.xy / 5.0)).rgb - 0.5).rbg * noiseScale; + final += noiseNormal.xz; + +// final.x = clamp(1.0 + final.x - floor(1.0 + final.x), 0.0, 1.0); +// float m = 0.2; +// final.y = final.y * (1.0 - m) + m * 0.5; +// final.y = clamp(1.0 + final.y - floor(1.0 + final.y), 0.0, 1.0); + + vec3 N = t0.xyz + t1.xyz + t2.xyz; + N = normalize(rotMatrix * N); + vec3 E = normalize(eyeVector); + vec3 R = reflect(E, N); + R.z = -R.z; + // vec4 reflection = vec4(0.4, 0.4, 0.8, 1.0); + // vec4 reflection = textureCube(EnvironmentMap, R, reflectionBlur); + // Reflection / refraction + + vec4 reflectionColour = texture2D(reflectMap, final); + vec4 refractionColour = texture2D(refractMap, final) + tintColour; + reflectionColour.rgb *= (reflectionColour.r + reflectionColour.g + reflectionColour.b) * hdrMultiplier; + float facing = 1.0 - dot(-E, N); + + // float fresnel = clamp(fresnelBias + pow(facing, fresnelPower), 0.0, 1.0); + float fresnel = clamp(fresnelBias + fresnelScale * pow(1.0 + dot(eyeDir, oNormal), fresnelPower), 0.0, 1.0); + vec4 waterColor = mix(shallowColor, deepColor, facing) * waterAmount; + vec4 reflection = mix(waterColor, reflectionColour, fresnel) * reflectionAmount; + // reflection = mix(waterColor, reflection * reflectionColor, fresnel) * reflectionAmount; + // gl_FragColor = mix(waterColor, reflectionColour, reflectionAmount); + vec4 r = mix(refractionColour, reflectionColour, fresnel) * reflectionAmount; + gl_FragColor = waterColor + r; + //gl_FragColor = waterColor + mix(refractionColour, reflection, fresnel); + //gl_FragColor = refractionColour; + //gl_FragColor = reflectionColour; + //gl_FragColor = ambient * diffuse; +} diff --git a/water/water.h b/water/water.h new file mode 100644 index 0000000..a8f0b3b --- /dev/null +++ b/water/water.h @@ -0,0 +1,25 @@ +#ifndef MAT_WATER_H +#define MAT_WATER_H +#include +class App; +class Water : public Ogre::FrameListener, Ogre::RenderTargetListener { + Ogre::SceneManager *mScnMgr; + Ogre::SceneNode *mWaterNode, *mCameraNode; + Ogre::Vector3 mCameraPosition; + Ogre::Camera *mCamera; + Ogre::Plane mWaterPlane; + +public: + Water(); + virtual ~Water(); + void createWater(Ogre::Camera *camera); + void updateWater(float delta); + bool frameEnded(const Ogre::FrameEvent &evt) override; + bool frameRenderingQueued(const Ogre::FrameEvent &evt) override; + void preRenderTargetUpdate(const Ogre::RenderTargetEvent &evt) override; + void + postRenderTargetUpdate(const Ogre::RenderTargetEvent &evt) override; + void add_submerged_entity(Ogre::Entity *ent); + void add_surface_entity(Ogre::Entity *ent); +}; +#endif \ No newline at end of file diff --git a/water/water.material b/water/water.material new file mode 100644 index 0000000..c3a68fe --- /dev/null +++ b/water/water.material @@ -0,0 +1,81 @@ +/* +//---------------------------- +// Distortion effects +//---------------------------- +vertex_program Examples/FresnelRefractReflectVP glsl glsles glslang hlsl +{ + source Example_FresnelVp.glsl +} +fragment_program Examples/FresnelRefractReflectFP glsl glsles glslang hlsl +{ + source Example_FresnelFp.glsl + default_params + { + // assign samplers as required by GLSL + param_named noiseMap int 0 + param_named reflectMap int 1 + param_named refractMap int 2 + } +} + +*/ + +material Water +{ + technique + { + pass + { + ambient 1.0 1.0 1.0 1.0 + diffuse 0.0 0.2 0.5 1.0 +/* + vertex_program_ref Examples/FresnelRefractReflectVP + { + param_named_auto worldViewProjMatrix worldviewproj_matrix + param_named_auto textureProjMatrix texture_worldviewproj_matrix 0 + param_named_auto eyePosition camera_position_object_space + param_named_auto timeVal time 0.05 + param_named scroll float 1 + param_named scale float 1 + param_named noise float 1 + // scroll and noisePos will need updating per frame + } + fragment_program_ref Examples/FresnelRefractReflectFP + { + param_named fresnelBias float -0.1 + param_named fresnelScale float 1.8 + param_named fresnelPower float 8 + param_named tintColour float4 0 0.05 0.05 1 + param_named noiseScale float 0.05 + } +*/ + vertex_program_ref water_vp + { + } + fragment_program_ref water_fp + { + } + // Noise + texture_unit + { + // Perlin noise volume + texture waves2.png + // min / mag filtering, no mip + filtering linear linear none + } + // Reflection + texture_unit + { + content_type compositor Fresnel reflection + tex_address_mode mirror + } + // Refraction + texture_unit + { + content_type compositor Fresnel refraction + tex_address_mode mirror + } + } + } +} + diff --git a/water/water.program b/water/water.program new file mode 100644 index 0000000..d165975 --- /dev/null +++ b/water/water.program @@ -0,0 +1,53 @@ +fragment_program water_fp glsl glsles glslang hlsl +{ + source water.frag + default_params + { + param_named_auto ambient surface_ambient_colour + param_named_auto diffuse surface_diffuse_colour + param_named_auto time time +// param_named NormalMap int 0 +// param_named EnvironmentMap int 1 + param_named deepColor float4 0 0.2 0.5 1.0 + param_named shallowColor float4 0 0.8 1 1.0 + param_named reflectionColor float4 0.95 1 1 1.0 + param_named reflectionAmount float 0.5 + param_named reflectionBlur float 0.0 + param_named waterAmount float 0.5 +// param_named fresnelPower float 5.0 +// param_named fresnelPower float 8.0 + param_named fresnelPower float 2.0 +// param_named fresnelBias float 0.328 + param_named fresnelBias float 0.328 +// param_named fresnelScale float 1.8 +// param_named fresnelScale float 1.8 + param_named fresnelScale float 1.0 + param_named hdrMultiplier float 0.471 + param_named tintColour float4 0 0.05 0.05 1 + param_named noiseScale float 0.03 + param_named noiseMap int 0 + param_named reflectMap int 1 + param_named refractMap int 2 + } +} + +vertex_program water_vp glsl glsles glslang hlsl +{ + source water.vert + default_params + { + param_named_auto worldViewProj worldviewproj_matrix + param_named_auto textureProjMatrix texture_worldviewproj_matrix 0 + param_named_auto eyePosition camera_position_object_space + param_named BumpScale float 0.2 + param_named textureScale float2 25 26 + param_named bumpSpeed float2 0.015 0.005 + param_named_auto time time_0_x 100.0 + param_named waveFreq float 0.028 + param_named waveAmp float 1.0 + param_named scroll float 1 + param_named scale float 1 + param_named noise float 1 + } +} + diff --git a/water/water.vert b/water/water.vert new file mode 100644 index 0000000..c45715f --- /dev/null +++ b/water/water.vert @@ -0,0 +1,108 @@ +/*********************************************************************NVMH3**** +Copyright NVIDIA Corporation 2003 +TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THIS SOFTWARE IS PROVIDED +*AS IS* AND NVIDIA AND ITS SUPPLIERS DISCLAIM ALL WARRANTIES, EITHER EXPRESS +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL NVIDIA OR ITS SUPPLIERS +BE LIABLE FOR ANY SPECIAL, INCIDENTAL, INDIRECT, OR CONSEQUENTIAL DAMAGES +WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS, +BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR ANY OTHER PECUNIARY LOSS) +ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF NVIDIA HAS +BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + + +Comments: + Simple ocean shader with animated bump map and geometric waves + Based partly on "Effective Water Simulation From Physical Models", GPU Gems + +11 Aug 05: converted from HLSL to GLSL by Jeff Doyle (nfz) to work in Ogre +15 Jun 25: modified to work with OgreUnifiedShader.h + +******************************************************************************/ +OGRE_NATIVE_GLSL_VERSION_DIRECTIVE +#include +#line 3 + +OGRE_UNIFORMS( +uniform vec3 eyePosition; +uniform float BumpScale; +uniform vec2 textureScale; +uniform vec2 bumpSpeed; +uniform highp float time; +uniform float waveFreq; +uniform float waveAmp; +uniform mat4 worldViewProj; +uniform mat4 textureProjMatrix; +uniform mat3 normalMatrix; +uniform float scale; // the amount to scale the noise texture by +uniform float scroll; // the amount by which to scroll the noise +uniform float noise; // the noise perturb as a factor of the time +) +// wave functions +struct Wave { + float freq; // 2*PI / wavelength + float amp; // amplitude + float phase; // speed * 2*PI / wavelength + vec2 dir; +}; + +MAIN_PARAMETERS +IN(vec4 vertex, POSITION) +IN(vec3 normal, NORMAL) +// IN(vec3 tangent, TANGENT) +IN(vec3 uv0, TEXCOORD0) +OUT(mat3 rotMatrix, 17) +OUT(vec2 bumpCoord0, 18) +OUT(vec2 bumpCoord1, 19) +OUT(vec2 bumpCoord2, 20) +OUT(vec3 eyeVector, 21) +OUT(vec3 noiseCoord, 22) +OUT(highp vec4 projectionCoord, 23) +OUT(vec3 eyeDir, 24) +OUT(vec3 oNormal, 25) +MAIN_DECLARATION +{ +#define NWAVES 4 + Wave wave[NWAVES]; + wave[0] = Wave( waveFreq, waveAmp, 0.5, vec2(-1.0, 0.0) ); + wave[1] = Wave( 3.0 * waveFreq, 0.33 * waveAmp, 1.7, vec2(-0.7, 0.7) ); + wave[2] = Wave( 7.5 * waveFreq, 0.15 * waveAmp, 2.9, vec2(-0.2, 0.2) ); + wave[3] = Wave( 11.5 * waveFreq, 0.075 * waveAmp, 5.9, vec2(-0.2, 0.3) ); + vec4 P = worldViewProj * vertex; + vec4 R = vertex; + // sum waves + float ddx = 0.0, ddy = 0.0; + float deriv; + float angle; + projectionCoord = mul(textureProjMatrix, vertex); + + // Noise map coords + noiseCoord.xy = (uv0.xy + (time * scroll)) * scale; + noiseCoord.z = noise * time; + // wave synthesis using two sine waves at different frequencies and phase shift + for(int i = 0; i