This commit is contained in:
2025-06-16 01:49:08 +03:00
parent a1f1e09af6
commit 82df3bb299
13 changed files with 562 additions and 41 deletions

View File

@@ -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(

View File

@@ -8,8 +8,10 @@
#include <OgreImGuiInputListener.h>
#include <OgreTrays.h>
#include <OgreTimer.h>
#include <OgreMeshLodGenerator.h>
#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<Ogre::Bullet::DynamicsWorld> mDynWorld;
std::unique_ptr<Ogre::Bullet::DebugDrawer> 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)
{

View File

@@ -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

View File

@@ -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
}
}

View File

@@ -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);
}
};

23
water/water.compositor Normal file
View File

@@ -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
}
}
}

122
water/water.cpp Normal file
View File

@@ -0,0 +1,122 @@
#include <Ogre.h>
#include <OgreMeshLodGenerator.h>
#include <OgreCompositorManager.h>
#include <OgreMaterialManager.h>
#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);
}

103
water/water.frag Normal file
View File

@@ -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 <OgreUnifiedShader.h>
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;
}

25
water/water.h Normal file
View File

@@ -0,0 +1,25 @@
#ifndef MAT_WATER_H
#define MAT_WATER_H
#include <Ogre.h>
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

81
water/water.material Normal file
View File

@@ -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
}
}
}
}

53
water/water.program Normal file
View File

@@ -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
}
}

108
water/water.vert Normal file
View File

@@ -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 <OgreUnifiedShader.h>
#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<NWAVES; ++i)
{
angle = dot(wave[i].dir, P.xz) * wave[i].freq + time * wave[i].phase;
P.y += wave[i].amp * sin( angle );
// calculate derivate of wave function
deriv = wave[i].freq * wave[i].amp * cos(angle);
ddx -= deriv * wave[i].dir.x;
ddy -= deriv * wave[i].dir.y;
}
R.y = P.y;
// compute the 3x3 transform from tangent space to object space
// compute tangent basis
vec3 T = normalize(vec3(1.0, ddy, 0.0)) * BumpScale;
vec3 B = normalize(vec3(0.0, ddx, 1.0)) * BumpScale;
vec3 N = normalize(vec3(ddx, 1.0, ddy));
rotMatrix = mat3(T, B, N);
gl_Position = P;
// calculate texture coordinates for normal map lookup
bumpCoord0.xy = uv0.xy * textureScale + time * bumpSpeed;
bumpCoord1.xy = uv0.xy * textureScale * 2.0 + time * bumpSpeed * 4.0;
bumpCoord2.xy = uv0.xy * textureScale * 4.0 + time * bumpSpeed * 8.0;
eyeVector = R.xyz - eyePosition; // eye position in vertex space
eyeDir = normalize(R.xyz - eyePosition);
oNormal = normal;
}

BIN
water/waves2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 167 KiB