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

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