Render target water

This commit is contained in:
2025-07-04 01:10:08 +03:00
parent f58402921f
commit b2e010bdb4
11 changed files with 405 additions and 179 deletions

View File

@@ -15,24 +15,34 @@ set(CREATE_SCENES
${CMAKE_SOURCE_DIR}/characters/male/vroid-normal-male.scene
)
option(OGRE_DYNAMIC "Build against dynamic ogre" ON)
# workaround horribly broken assimp cmake, fixed with assimp 5.1
add_library(fix::assimp INTERFACE IMPORTED)
set_target_properties(fix::assimp PROPERTIES
INTERFACE_LINK_LIBRARIES "${ASSIMP_LIBRARIES};pugixml"
INTERFACE_LINK_DIRECTORIES "${ASSIMP_LIBRARY_DIRS}"
)
#add_library(assimp INTERFACE IMPORTED)
#set_target_properties(assimp PROPERTIES
# INTERFACE_LINK_LIBRARIES "assimp;pugixml"
# # INTERFACE_LINK_DIRECTORIES "${ASSIMP_LIBRARY_DIRS}"
# INTERFACE_LINK_DIRECTORIES "${CMAKE_PREFIX_PATH}/lib"
#)
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
find_package(OGRE REQUIRED COMPONENTS Bites Bullet Paging CONFIG)
find_package(OGRE REQUIRED COMPONENTS Bites Bullet Paging Terrain CONFIG)
find_package(ZLIB)
find_package(SDL2)
find_package(assimp)
find_package(assimp REQUIRED CONFIG)
find_package(Bullet)
find_package(OgreProcedural REQUIRED CONFIG)
find_package(pugixml REQUIRED CONFIG)
add_library(fix::assimp INTERFACE IMPORTED)
set_target_properties(fix::assimp PROPERTIES
INTERFACE_LINK_LIBRARIES "${ASSIMP_LIBRARIES};pugixml"
INTERFACE_LINK_DIRECTORIES "${ASSIMP_LIBRARY_DIRS}"
# INTERFACE_LINK_DIRECTORIES "${CMAKE_PREFIX_PATH}/lib"
)
add_library(fix::OgreProcedural INTERFACE IMPORTED)
set_target_properties(fix::OgreProcedural PROPERTIES
@@ -40,6 +50,21 @@ set_target_properties(fix::OgreProcedural PROPERTIES
INTERFACE_LINK_DIRECTORIES "${CMAKE_PREFIX_PATH}/lib"
)
if(NOT OGRE_DYNAMIC)
add_library(OgreGLSupportStatic INTERFACE IMPORTED)
set_target_properties(OgreGLSupportStatic PROPERTIES
INTERFACE_LINK_LIBRARIES "OgreGLSupportStatic"
INTERFACE_LINK_DIRECTORIES "${CMAKE_PREFIX_PATH}/lib"
)
endif()
add_library(fix::pugixml INTERFACE IMPORTED)
set_target_properties(fix::pugixml PROPERTIES
INTERFACE_LINK_LIBRARIES "pugixml"
INTERFACE_LINK_DIRECTORIES "${CMAKE_PREFIX_PATH}/lib"
)
add_subdirectory(src/lua)
@@ -47,7 +72,7 @@ add_subdirectory(src/lua)
add_executable(0_Bootstrap Bootstrap.cpp)
# this also sets the includes and pulls third party dependencies
target_link_libraries(0_Bootstrap OgreBites OgreBullet OgrePaging ${BULLET_DYNAMICS_LIBRARY} ${BULLET_COLLISION_LIBRARY} ${BULLET_MATH_LIBRARY})
target_link_libraries(0_Bootstrap OgreBites OgreBullet OgrePaging ${BULLET_DYNAMICS_LIBRARY} ${BULLET_COLLISION_LIBRARY} ${BULLET_MATH_LIBRARY} ${ASSIMP_LIBRARIES})
target_include_directories(0_Bootstrap PUBLIC OgreBites OgrePaging OgreBullet)
add_dependencies(0_Bootstrap stage_files)
@@ -60,7 +85,6 @@ add_executable(Procedural Procedural.cpp ${TERRAIN_SRC})
target_link_libraries(Procedural OgreBites OgreBullet OgrePaging OgreTerrain OgreProcedural::OgreProcedural ${BULLET_DYNAMICS_LIBRARY} ${BULLET_COLLISION_LIBRARY} ${BULLET_MATH_LIBRARY})
target_include_directories(Procedural PUBLIC OgreBites OgrePaging OgreBullet OgreTerrain OgreProcedural::OgreProcedural ${CMAKE_PREFIX_PATH}/include/OgreProcedural)
add_dependencies(Procedural stage_files import_buildings)
file(GLOB BUILDINGS_SRC ${CMAKE_SOURCE_DIR}/assets/blender/buildings/*.blend)
set(BUILDING_OUTPUT_FILES)
foreach(BUILDING_FILE ${BUILDINGS_SRC})
@@ -83,6 +107,13 @@ add_custom_target(import_buildings ALL DEPENDS ${BUILDING_OUTPUT_FILES})
add_executable(TerrainTest terrain.cpp ${TERRAIN_SRC})
target_link_libraries(TerrainTest OgreBites OgreBullet OgrePaging OgreTerrain lua ${BULLET_DYNAMICS_LIBRARY} ${BULLET_COLLISION_LIBRARY} ${BULLET_MATH_LIBRARY})
target_include_directories(TerrainTest PUBLIC OgreBites OgrePaging OgreTerrain OgreBullet PRIVATE . src/terrain src/lua src/lua/lua-5.4.8/src)
if(NOT OGRE_DYNAMIC)
target_link_libraries(TerrainTest fix::assimp pugixml)
target_link_libraries(Procedural fix::assimp pugixml)
target_link_libraries(0_Bootstrap fix::assimp pugixml)
target_link_libraries(GuiTest fix::assimp pugixml)
endif()
file(GLOB LUA_SCRIPTS_SRC ${CMAKE_SOURCE_DIR}/lua-scripts/*.lua)
set(LUA_SCRIPTS_OUTPUT)
@@ -150,6 +181,8 @@ set(WATER_SRC
water.program
water.frag
water.vert
depth.frag
depth.vert
water.compositor
waves2.png
)
@@ -201,3 +234,5 @@ add_custom_target(remove_scenes COMMAND rm -f ${CREATE_SCENES})
add_custom_target(import_vrm DEPENDS ${CREATE_SCENES})
install(TARGETS GuiTest DESTINATION bin)

View File

@@ -395,10 +395,13 @@ public:
mDbgDraw.reset(new Ogre::Bullet::DebugDrawer(
mScnMgr->getRootSceneNode(), mDynWorld->getBtWorld()));
}
void locateResources()
void locateResources() override
{
OgreBites::ApplicationContext::locateResources();
}
void loadResources() override
{
}
void initCamera()
{
@@ -429,8 +432,38 @@ public:
// our model is quite small, so reduce the clipping planes
mCamera->setNearClipDistance(0.1f);
mCamera->setFarClipDistance(800);
mPivotPitch = 0;
}
void configure()
{
std::cout << "Startup" << "\n";
initApp();
std::cout << "Set up RTSS" << "\n";
Ogre::Root *root = getRoot();
Ogre::SceneManager *scnMgr = getSceneManager();
// register our scene with the RTSS
Ogre::RTShader::ShaderGenerator *shadergen =
Ogre::RTShader::ShaderGenerator::getSingletonPtr();
shadergen->addSceneManager(scnMgr);
setWindowGrab(true);
std::cout << "Init camera" << "\n";
initCamera();
std::cout << "Set up water" << "\n";
m_water.createWater(getRenderWindow(), mCamera);
std::cout << "Set up cursor" << "\n";
Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
// OgreBites::ApplicationContext::loadResources();
setupCursor();
std::cout << "Create content" << "\n";
createContent();
std::cout << "Setup terrain" << "\n";
setupTerrain();
m_water.init();
}
void setupCursor()
{
// mKeyDirection = Ogre::Vector3::ZERO;
// mVerticalVelocity = 0;
Ogre::ManualObject *mobj =
@@ -600,7 +633,7 @@ public:
Ogre::Timer mTerrainUpd;
void updateTerrain(float delta)
{
mDbgDraw->update();
// mDbgDraw->update();
#if 0
if (mTerrainUpd.getMilliseconds() > 1000) {
m_terrain.create_colliders();
@@ -641,7 +674,6 @@ public:
"Skybox/Dynamic", "General");
OgreAssert(m, "Sky box material not found.");
m->load();
m_water.createWater(mCamera);
getRoot()->addFrameListener(&m_water);
#endif
}
@@ -845,20 +877,9 @@ void EditUI::initGui()
int main()
{
App ctx;
ctx.initApp();
ctx.configure();
// ctx.runRenderingSettingsDialog();
// get a pointer to the already created root
Ogre::Root *root = ctx.getRoot();
Ogre::SceneManager *scnMgr = ctx.getSceneManager();
// register our scene with the RTSS
Ogre::RTShader::ShaderGenerator *shadergen =
Ogre::RTShader::ShaderGenerator::getSingletonPtr();
shadergen->addSceneManager(scnMgr);
ctx.setWindowGrab(true);
ctx.initCamera();
ctx.createContent();
ctx.setupTerrain();
// register for input events
// KeyHandler keyHandler;
// ctx.addInputListener(&keyHandler);

View File

@@ -19,9 +19,9 @@ FileSystem=resources/terrain
# samples which require them.
[General]
FileSystem=skybox
FileSystem=water
FileSystem=resources/buildings
FileSystem=resources/debug
FileSystem=water
# PBR media must come before the scripts that reference it
#FileSystem=./Media/PBR
#FileSystem=./Media/PBR/filament
@@ -73,4 +73,3 @@ FileSystem=lua-scripts
[Characters]
FileSystem=./characters/male
FileSystem=./characters/female

View File

@@ -21,7 +21,7 @@
#define ENDLESS_TERRAIN_FILE_PREFIX Ogre::String("EndlessWorldTerrain")
#define ENDLESS_TERRAIN_FILE_SUFFIX Ogre::String("dat")
#define TERRAIN_WORLD_SIZE 4000.0f
#define TERRAIN_SIZE 129
#define TERRAIN_SIZE 513
// #define HOLD_LOD_DISTANCE 3000.0
#define USE_PERLIN_DEFINER 0
template <typename T> T CLAMP(T value, T low, T high)
@@ -258,7 +258,8 @@ public:
if (!created || true) {
btRigidBody *body =
mWorld->addTerrainRigidBody(
group, x, y);
group, x, y, 2,
0x7ffffffd);
Ogre::LogManager::getSingleton().logError(
"created rigid body " +
Ogre::StringConverter::toString(

View File

@@ -1,9 +1,11 @@
/*
compositor Fresnel
{
technique
{
texture reflection 512 512 PF_BYTE_RGB
texture refraction 512 512 PF_BYTE_RGB
target reflection
{
visibility_mask 0x00F // SURFACE objects
@@ -20,4 +22,5 @@ compositor Fresnel
}
}
}
*/

View File

@@ -1,3 +1,4 @@
#include <iostream>
#include <Ogre.h>
#include <OgreMeshLodGenerator.h>
#include <OgreCompositorManager.h>
@@ -9,10 +10,18 @@ static const uint32_t SURFACE_MASK = 0x00F;
static const uint32_t WATER_MASK = 0xF00;
Water::Water()
: FrameListener()
, RenderTargetListener()
, mWaterNode(nullptr)
, mScnMgr(nullptr)
, mWindow(nullptr)
, mCameraNode(nullptr)
, mWaterPlane(Ogre::Vector3::UNIT_Y, 0)
, mReflectionPlane(Ogre::Vector3(0.0, 1.0, 0.0), 0.0f /* water height */)
, mReflectionClipPlaneAbove(Ogre::Vector3(0.0, 1.0, 0.0), 0.0f /* water height */ - 2.0f)
, mReflectionClipPlaneBelow(Ogre::Vector3(0.0, -1.0, 0.0), -(0.0f /* water height */ + 2.0))
, mRefractionClipPlaneAbove(Ogre::Vector3(0.0, -1.0, 0.0), -(0.0f /* water height */ + 2.0))
, mRefractionClipPlaneBelow(Ogre::Vector3(0.0, 1.0, 0.0), 0.0f /* water height */ - 2.0)
, mAbove(true)
{
}
@@ -20,30 +29,75 @@ Water::~Water()
{
if (mWaterNode)
mScnMgr->destroySceneNode(mWaterNode);
if(mReflectionTexture)
mReflectionTexture->removeAllListeners();
}
void Water::createWater(Ogre::Camera *camera)
void Water::create_cameras()
{
mReflectionTexture->addListener(this);
mReflectionCamera = mScnMgr->createCamera("ReflectionCamera");
mCamera->getParentSceneNode()->attachObject(mReflectionCamera);
mReflectionCamera->setAspectRatio(mCamera->getAspectRatio());
mReflectionCamera->setNearClipDistance(mCamera->getNearClipDistance());
mReflectionCamera->setFarClipDistance(mCamera->getFarClipDistance());
mReflectionCamera->enableCustomNearClipPlane(mReflectionClipPlaneAbove);
mReflectionCamera->enableReflection(mReflectionPlane);
Ogre::Viewport * reflectionViewport = mReflectionTexture->addViewport(mReflectionCamera);
reflectionViewport->setClearEveryFrame(true);
reflectionViewport->setBackgroundColour(Ogre::ColourValue(0.0, 0.0, 0.0, 0.0));
reflectionViewport->setOverlaysEnabled(false);
// reflectionViewport->setVisibilityMask(0xFFF);
mRefractionTexture->addListener(this);
mRefractionCamera = mScnMgr->createCamera("RefractionCamera");
mCamera->getParentSceneNode()->attachObject(mRefractionCamera);
mRefractionCamera->setAspectRatio(mCamera->getAspectRatio());
mRefractionCamera->setNearClipDistance(mCamera->getNearClipDistance());
mRefractionCamera->setFarClipDistance(mCamera->getFarClipDistance());
mRefractionCamera->enableCustomNearClipPlane(mRefractionClipPlaneAbove);
Ogre::Viewport * refractionViewport = mRefractionTexture->addViewport(mRefractionCamera);
refractionViewport->setClearEveryFrame(true);
refractionViewport->setBackgroundColour(Ogre::ColourValue(0.0, 0.0, 0.0, 0.0));
refractionViewport->setOverlaysEnabled(false);
refractionViewport->setSkiesEnabled(false);
}
void Water::create_textures()
{
Ogre::TexturePtr reflectionTexture = Ogre::TextureManager::getSingleton().createManual(
"ReflectionTexture",
Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
Ogre::TEX_TYPE_2D, 256, 256,
0,
Ogre::PF_R8G8B8A8,
Ogre::TU_RENDERTARGET);
mReflectionTexture = reflectionTexture->getBuffer()->getRenderTarget();
Ogre::TexturePtr refractionTexture = Ogre::TextureManager::getSingleton().createManual(
"RefractionTexture",
Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
Ogre::TEX_TYPE_2D, 512, 512,
0,
Ogre::PF_R8G8B8A8,
Ogre::TU_RENDERTARGET);
mRefractionTexture = refractionTexture->getBuffer()->getRenderTarget();
}
void Water::init()
{
int i;
float w = 1000;
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);
float w = 600.0f;
// mWindow->addListener(this);
create_cameras();
Ogre::MeshPtr water_plane =
Ogre::MeshManager::getSingleton().createPlane(
"water",
Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
mWaterPlane, w, w, 100, 100, true, 1, 100, 100,
mWaterPlane, w, w, 10, 10, true, 1, 100, 100,
Ogre::Vector3::UNIT_Z);
if (!Ogre::MeshLodGenerator::getSingletonPtr())
new Ogre::MeshLodGenerator();
@@ -53,45 +107,82 @@ void Water::createWater(Ogre::Camera *camera)
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 } };
Ogre::Vector3 positions[] = { { 0, 0, 0 }, { 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);
water->setCastShadows(true);
auto mat = Ogre::MaterialManager::getSingleton().getByName("Water");
auto mat = Ogre::MaterialManager::getSingleton().getByName("Water/Above");
mat->load();
mat->setReceiveShadows(false);
#if 0
mat->getTechnique(0)
->getPass(0)
->getTextureUnitState(0)
->setProjectiveTexturing(true, mCamera);
water->setMaterial(mat);
Ogre::SceneNode *node0 = mWaterNode->createChildSceneNode("WaterR");
node0->attachObject(water);
#endif
auto mat2 = Ogre::MaterialManager::getSingleton().getByName("Water/Below");
mat2->load();
mat2->setReceiveShadows(false);
#if 0
mat2->getTechnique(0)
->getPass(0)
->getTextureUnitState(0)
->setProjectiveTexturing(true, mCamera);
#endif
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");
water_lod1->setVisibilityFlags(WATER_MASK);
water_lod1->setCastShadows(true);
water_lod1->setMaterialName("Water/Above");
water_lod1->setMaterial(mat);
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);
mWaterMeshes.push_back(water_lod1);
}
}
void Water::createWater(Ogre::RenderWindow * window, Ogre::Camera *camera)
{
int i;
mCamera = camera;
mScnMgr = camera->getSceneManager();
mCameraNode = camera->getParentSceneNode();
Ogre::Viewport *viewport = camera->getViewport();
mWindow = window;
mCameraPosition = mCameraNode->getPosition();
create_textures();
}
void Water::updateWater(float delta)
{
int i;
if (mCameraPosition.squaredDistance(mCameraNode->getPosition()) >
100.0f) {
200.0f * 200.0f) {
mCameraPosition = mCameraNode->getPosition();
Ogre::Vector3 waterPosition = mCameraPosition;
waterPosition.y = 0;
mWaterNode->setPosition(waterPosition);
}
if (mAbove) {
if (mCameraNode->getPosition().y < 0) {
mAbove = false;
for (i = 0; i < mWaterMeshes.size(); i++)
mWaterMeshes[i]->setMaterialName("Water/Below");
}
} else {
if (mCameraNode->getPosition().y > 0) {
mAbove = true;
for (i = 0; i < mWaterMeshes.size(); i++)
mWaterMeshes[i]->setMaterialName("Water/Above");
}
}
}
bool Water::frameEnded(const Ogre::FrameEvent &evt)
@@ -106,12 +197,25 @@ bool Water::frameRenderingQueued(const Ogre::FrameEvent &evt)
void Water::preRenderTargetUpdate(const Ogre::RenderTargetEvent &evt)
{
mCamera->enableReflection(mWaterPlane);
int i;
if (evt.source == mReflectionTexture || evt.source == mRefractionTexture) {
for (i = 0; i < mWaterMeshes.size(); i++)
mWaterMeshes[i]->setVisible(false);
if (evt.source == mReflectionTexture)
mInRefTexUpdate = true;
} else {
for (i = 0; i < mWaterMeshes.size(); i++)
mWaterMeshes[i]->setVisible(true);
mInRefTexUpdate = false;
}
}
void Water::postRenderTargetUpdate(const Ogre::RenderTargetEvent &evt)
{
mCamera->disableReflection();
int i;
for (i = 0; i < mWaterMeshes.size(); i++)
mWaterMeshes[i]->setVisible(true);
mInRefTexUpdate = false;
}
void Water::add_submerged_entity(Ogre::Entity *ent)
@@ -123,3 +227,8 @@ void Water::add_surface_entity(Ogre::Entity *ent)
{
ent->setVisibilityFlags(SURFACE_MASK);
}
void Water::dump_textures()
{
mReflectionTexture->writeContentsToFile("Reflection.png");
mRefractionTexture->writeContentsToFile("Refraction.png");
}

View File

@@ -1,103 +1,24 @@
/*********************************************************************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);
// SAMPLER2D(noiseMap, 0);
SAMPLER2D(reflectMap, 0);
SAMPLER2D(refractMap, 1);
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;
uniform vec4 viewportSize;
uniform f32vec4 cameraPosition;
)
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)
IN(highp vec4 projectionCoord, TEXCOORD4)
IN(f32vec3 positionWS, TEXCOORD7)
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;
vec2 screenUV = gl_FragCoord.xy / viewportSize.xy;
screenUV.y = 1.0 - screenUV.y * 0.6 - 0.2;
// vec2 final = projectionCoord.xy / projectionCoord.w;
float depth = saturate(length(positionWS - cameraPosition.xyz) * 0.01);
vec4 reflectionColour = texture2D(reflectMap, screenUV);
vec4 refractionColour = texture2D(refractMap, screenUV);
vec4 result = mix(mix(reflectionColour, refractionColour, 0.5), vec4(0.0, 1.0, 1.0, 1.0), depth);
result.a = 1.0;
gl_FragColor = result;
}

View File

@@ -4,15 +4,35 @@
class App;
class Water : public Ogre::FrameListener, Ogre::RenderTargetListener {
Ogre::SceneManager *mScnMgr;
Ogre::RenderWindow * mWindow;
Ogre::SceneNode *mWaterNode, *mCameraNode;
Ogre::Vector3 mCameraPosition;
Ogre::Camera *mCamera;
Ogre::Plane mWaterPlane;
Ogre::Plane mWaterPlane,
mReflectionPlane,
mReflectionClipPlaneAbove,
mReflectionClipPlaneBelow,
mRefractionClipPlaneAbove,
mRefractionClipPlaneBelow;
bool mAbove;
std::vector<Ogre::Entity *> mWaterMeshes;
// Reflection
Ogre::RenderTexture * mReflectionTexture;
Ogre::Camera * mReflectionCamera;
// Refraction
Ogre::RenderTexture * mRefractionTexture;
Ogre::Camera * mRefractionCamera;
bool mInRefTexUpdate;
Ogre::Timer mtexture_dump;
void create_cameras();
public:
Water();
virtual ~Water();
void createWater(Ogre::Camera *camera);
void create_textures();
void dump_textures();
void createWater(Ogre::RenderWindow * window, Ogre::Camera *camera);
void init();
void updateWater(float delta);
bool frameEnded(const Ogre::FrameEvent &evt) override;
bool frameRenderingQueued(const Ogre::FrameEvent &evt) override;
@@ -22,4 +42,4 @@ public:
void add_submerged_entity(Ogre::Entity *ent);
void add_surface_entity(Ogre::Entity *ent);
};
#endif
#endif

View File

@@ -20,7 +20,7 @@ fragment_program Examples/FresnelRefractReflectFP glsl glsles glslang hlsl
*/
material Water
material Water/Above
{
technique
{
@@ -51,12 +51,13 @@ material Water
param_named noiseScale float 0.05
}
*/
vertex_program_ref water_vp
vertex_program_ref Water/water_vp
{
}
fragment_program_ref water_fp
fragment_program_ref Water/water_fp
{
}
/*
// Noise
texture_unit
{
@@ -90,8 +91,96 @@ material Water
}
tex_address_mode mirror
}
*/
texture_unit
{
texture ReflectionTexture
tex_address_mode mirror
}
texture_unit
{
texture RefractionTexture
tex_address_mode mirror
}
}
}
}
material Water/Below
{
technique
{
pass
{
ambient 1.0 1.0 1.0 1.0
diffuse 0.0 0.2 0.5 1.0
cull_hardware none
cull_software none
vertex_program_ref Water/water_vp
{
}
fragment_program_ref Water/water_fp
{
}
/*
// Noise
texture_unit
{
// Perlin noise volume
texture waves2.png
// min / mag filtering, no mip
filtering linear linear none
tex_address_mode mirror
}
// Reflection
texture_unit
{
content_type compositor Fresnel reflection
tex_address_mode mirror
}
// Refraction
texture_unit
{
content_type compositor Fresnel refraction
tex_address_mode mirror
}
*/
texture_unit
{
texture ReflectionTexture
tex_address_mode mirror
}
texture_unit
{
texture RefractionTexture
tex_address_mode mirror
}
}
}
}
/*
material Water/Depth
{
technique
{
pass
{
cull_hardware none
alpha_rejection greater_equal 0.5
vertex_program_ref Water/depth_vp
{
param_named_auto world world_matrix
param_named_auto worldViewProj worldviewproj_matrix
}
fragment_program_ref Water/depth_fp
{
param_named_auto cameraPosition camera_position
}
}
}
}
*/

View File

@@ -1,10 +1,31 @@
fragment_program water_fp glsl glsles glslang hlsl
vertex_program Water/depth_vp glsl glsles glslang hlsl
{
source depth.vert
default_params
{
param_named_auto world world_matrix
param_named_auto worldViewProj worldviewproj_matrix
}
}
fragment_program Water/depth_fp glsl glsles glslang hlsl
{
source depth.frag
default_params
{
param_named_auto cameraPosition camera_position
}
}
fragment_program Water/water_fp glsl glsles glslang hlsl
{
source water.frag
default_params
{
param_named_auto cameraPosition camera_position
param_named_auto ambient surface_ambient_colour
param_named_auto diffuse surface_diffuse_colour
param_named_auto viewportSize viewport_size
param_named_auto time time
// param_named NormalMap int 0
// param_named EnvironmentMap int 1
@@ -25,17 +46,18 @@ fragment_program water_fp glsl glsles glslang hlsl
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
// param_named noiseMap int 0
param_named reflectMap int 0
param_named refractMap int 1
}
}
vertex_program water_vp glsl glsles glslang hlsl
vertex_program Water/water_vp glsl glsles glslang hlsl
{
source water.vert
default_params
{
param_named_auto world world_matrix
param_named_auto worldViewProj worldviewproj_matrix
param_named_auto textureProjMatrix texture_worldviewproj_matrix 0
param_named_auto eyePosition camera_position_object_space

View File

@@ -31,6 +31,7 @@ uniform vec2 bumpSpeed;
uniform highp float time;
uniform float waveFreq;
uniform float waveAmp;
uniform mat4 world;
uniform mat4 worldViewProj;
uniform mat4 textureProjMatrix;
uniform mat3 normalMatrix;
@@ -51,17 +52,17 @@ 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)
OUT(mat3 rotMatrix, TEXCOORD0)
OUT(vec4 bumpCoordA, TEXCOORD1)
OUT(vec4 bumpCoordB, TEXCOORD2)
OUT(vec3 noiseCoord, TEXCOORD3)
OUT(highp vec4 projectionCoord, TEXCOORD4)
OUT(vec3 eyeDir, TEXCOORD5)
OUT(vec3 oNormal, TEXCOORD6)
OUT(f32vec3 positionWS, TEXCOORD7)
MAIN_DECLARATION
{
#if 1
#define NWAVES 4
Wave wave[NWAVES];
wave[0] = Wave( waveFreq, waveAmp, 0.5, vec2(-1.0, 0.0) );
@@ -98,11 +99,16 @@ MAIN_DECLARATION
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;
bumpCoordA.xy = uv0.xy * textureScale + time * bumpSpeed;
bumpCoordA.zw = uv0.xy * textureScale * 2.0 + time * bumpSpeed * 4.0;
bumpCoordB.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;
oNormal = normalize(normal + N);
positionWS = mul(world, vertex).xyz;
#else
gl_Position = worldViewProj * vertex;
projectionCoord = mul(textureProjMatrix, vertex);
#endif
}