Realistic water scene node

Announce new projects or updates of Irrlicht Engine related tools, games, and applications.
Also check the Wiki
elvman
Posts: 253
Joined: Sun Sep 17, 2006 9:37 am
Location: Riga, Latvia
Contact:

Re: Realistic water scene node

Post by elvman »

Published the code on GitHub https://github.com/elvman/RealisticWaterSceneNode.
Last version is compatible and works (hopefully) with latest version of Irrlicht. Also now you have to pass resource path to constructor (instead of bumpmap texture), so that you can use it also on OSX. To use it on OSX you can pass something like this to it:

Code: Select all

std::string resourcePath()
{
    NSString* path = [[NSBundle mainBundle]resourcePath];
    
    return [path cStringUsingEncoding:NSASCIIStringEncoding];
}
Ouzel – 2D game engine
Realistic water node
elvman
Posts: 253
Joined: Sun Sep 17, 2006 9:37 am
Location: Riga, Latvia
Contact:

Re: Realistic water scene node (updated)

Post by elvman »

atul wrote:Great scene node, I've just noticed one minor issue: in the OnAnimate method of the RealisticWaterSceneNode class the position of _camera (the camera from which the reflection will be rendered) is calculated in terms of the relative position of the current active camera, but shouldn't this be the absolute position of the current active camera, especially considering that the targets of the cameras are always given in absolute coordinates? This was giving me trouble because I had a camera set up as a child of a mesh and the reflections were looking very strange.

So in short the following line of code

Code: Select all

core::vector3df position = currentCamera->getPosition();
should be changed to

Code: Select all

core::vector3df position = currentCamera->getAbsolutePosition();
Thanks! Pushed this fix to GitHub.
Ouzel – 2D game engine
Realistic water node
Nyx Erebos
Posts: 33
Joined: Fri Mar 01, 2013 1:26 am

Re: Realistic water scene node

Post by Nyx Erebos »

Does it work with Irrlicht 1.7.2 ? Because to make it compile I had to comment out all the services->getVertexShaderConstantID(...) and keep just the string. I tried to declare the node like that :

Code: Select all

RealisticWaterSceneNode * water = new RealisticWaterSceneNode(smgr,1000,1000,"path/to/data",dimension2du(512,512),smgr->getRootSceneNode(),10);
But when I run the program the screen is black. I tried to switch video::EVST_VS_1_1 with video::EVST_VS_2_0 and video::EPST_PS_1_1 with video::EPST_PS_2_0 but with no success.

I see that the code in the render() method is commented, is it normal ?

Maybe it's me being too lazy, do I have to initialize other parameters ? A little code sample would be great, thanks.
elvman
Posts: 253
Joined: Sun Sep 17, 2006 9:37 am
Location: Riga, Latvia
Contact:

Re: Realistic water scene node

Post by elvman »

Nyx Erebos wrote:Maybe it's me being too lazy, do I have to initialize other parameters ? A little code sample would be great, thanks.
Added support for Irrlicht 1.8 (get the newest version from GitHub). You must add something to scene (at least skybox and terrain) to actually see the water, because it reflects and refracts other objects.
Ouzel – 2D game engine
Realistic water node
Nyx Erebos
Posts: 33
Joined: Fri Mar 01, 2013 1:26 am

Re: Realistic water scene node

Post by Nyx Erebos »

Okay I understand the problem now, I'm using XEffects for lights/shadows so the smgr->drawall() is replaced by effect->update(). I'll try to find a workaround because when I replace the drawall by update in your code, it doesn't show water (there's some kind of underwater effect though) and the controls are inverted.
elvman
Posts: 253
Joined: Sun Sep 17, 2006 9:37 am
Location: Riga, Latvia
Contact:

Re: Realistic water scene node

Post by elvman »

Added fog support for GLSL. Will add this to HLSL later.
Image
Ouzel – 2D game engine
Realistic water node
Nyx Erebos
Posts: 33
Joined: Fri Mar 01, 2013 1:26 am

Re: Realistic water scene node

Post by Nyx Erebos »

Well I'll try to make your scene node work with xeffects later because there's too much black magic in xeffects for me at the moment :lol:
ikam
Posts: 46
Joined: Sun Jun 24, 2007 4:46 pm
Location: France

Re: Realistic water scene node

Post by ikam »

Thanks for the shader :), really nice.
I integrated the technique and the shader in another engine. It works great too.

Image
Mars_999
Posts: 136
Joined: Sat Dec 08, 2012 7:59 pm

Re: Realistic water scene node

Post by Mars_999 »

I am not sure what is wrong but I can't see nothing being rendered with this code base??

I am using the latest off github

I get no errors when running the code either...

RealisticWaterSceneNode* water = new RealisticWaterSceneNode(smgr, 2048, 2048, "C:/Programming/Work/TBSG/TBSG");

that is the call I make and that is it...

Code: Select all

 
/*
 * Copyright (c) 2013, elvman
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY elvman ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
#ifndef _REALISTIC_WATER_SCENE_NODE_H
#define _REALISTIC_WATER_SCENE_NODE_H
 
#include <irrlicht.h>
 
using namespace irr;
 
class RealisticWaterSceneNode: public scene::ISceneNode, video::IShaderConstantSetCallBack
{
public:
    RealisticWaterSceneNode(scene::ISceneManager* sceneManager, f32 width, f32 height,
                            const irr::core::stringc& resourcePath = irr::core::stringc(),
                            core::dimension2du renderTargetSize=core::dimension2du(512,512),scene::ISceneNode* parent = NULL, s32 id = -1);
    virtual ~RealisticWaterSceneNode();
 
    // frame
    virtual void OnRegisterSceneNode();
 
    virtual void OnAnimate(u32 timeMs);
 
    // renders terrain
    virtual void render();
    
    // returns the axis aligned bounding box of terrain
    virtual const core::aabbox3d<f32>& getBoundingBox() const;
 
    virtual void OnSetConstants(video::IMaterialRendererServices* services, s32 userData);
 
    void setWindForce(f32 windForce);
    void setWindDirection(const core::vector2df& windDirection);
    void setWaveHeight(f32 waveHeight);
 
    void setWaterColor(const video::SColorf& waterColor);
    void setColorBlendFactor(f32 colorBlendFactor);
 
private:
 
    scene::ICameraSceneNode*        _camera;
    scene::ISceneNode*              _waterSceneNode;
 
    video::IVideoDriver*            _videoDriver;
    scene::ISceneManager*           _sceneManager;
    
    core::dimension2d<f32>          _size;
 
    s32                             _shaderMaterial;
 
    scene::IAnimatedMesh*           _waterMesh;
 
    video::ITexture*                _refractionMap;
    video::ITexture*                _reflectionMap;
 
    f32                             _windForce;
    core::vector2df                 _windDirection;
    f32                             _waveHeight;
 
    video::SColorf                  _waterColor;
    f32                             _colorBlendFactor;
 
    u32                             _time;
};
 
#endif
 

Code: Select all

 
/*
 * Copyright (c) 2013, elvman
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY elvman ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
#include "stdafx.h"
 
RealisticWaterSceneNode::RealisticWaterSceneNode(scene::ISceneManager* sceneManager, f32 width, f32 height, 
                                                 const irr::core::stringc& resourcePath, core::dimension2du renderTargetSize,
                                                 scene::ISceneNode* parent, s32 id):
    scene::ISceneNode(parent, sceneManager, id), _time(0),
    _size(width, height), _sceneManager(sceneManager), _refractionMap(NULL), _reflectionMap(NULL),
    _windForce(20.0f),_windDirection(0, 1),_waveHeight(0.3f), _waterColor(0.1f, 0.1f, 0.6f, 1.0f), _colorBlendFactor(0.2f), _camera(NULL)
{
    _videoDriver = sceneManager->getVideoDriver();
 
    //create new camera
    _camera = sceneManager->addCameraSceneNode(0, core::vector3df(0, 0, 0), core::vector3df(0, 0, 0), -1, false);
    
    _waterMesh = sceneManager->addHillPlaneMesh("RealisticWater", _size, core::dimension2d<u32>(1, 1));
 
    _waterSceneNode = sceneManager->addMeshSceneNode(_waterMesh->getMesh(0), this);
 
    video::IGPUProgrammingServices* GPUProgrammingServices = _videoDriver->getGPUProgrammingServices();
 
    core::stringc waterPixelShader;
    core::stringc waterVertexShader;
 
    if (_videoDriver->getDriverType() == video::EDT_DIRECT3D9)
    {
        waterPixelShader  = resourcePath + "/media/shaders/Water_ps.hlsl";
        waterVertexShader = resourcePath + "/media/shaders/Water_vs.hlsl";
    }
    else if (_videoDriver->getDriverType() == video::EDT_OPENGL)
    {
        waterPixelShader  = resourcePath + "/media/shaders/Waterfs.glsl";
        waterVertexShader = resourcePath + "/media/shaders/Watervs.glsl";
    }
 
    _shaderMaterial = GPUProgrammingServices->addHighLevelShaderMaterialFromFiles(
        waterVertexShader.c_str(), "main", video::EVST_VS_3_0,
        waterPixelShader.c_str(),  "main", video::EPST_PS_3_0,
        this);
 
    _waterSceneNode->setMaterialType((video::E_MATERIAL_TYPE)_shaderMaterial);
 
    irr::video::ITexture* bumpTexture = _videoDriver->getTexture(resourcePath + "/media/textures/waterbump.png");
    _waterSceneNode->setMaterialTexture(0, bumpTexture);
 
    _refractionMap = _videoDriver->addRenderTargetTexture(renderTargetSize);
    _reflectionMap = _videoDriver->addRenderTargetTexture(renderTargetSize);
 
    _waterSceneNode->setMaterialTexture(1, _refractionMap);
    _waterSceneNode->setMaterialTexture(2, _reflectionMap);
}
 
RealisticWaterSceneNode::~RealisticWaterSceneNode()
{
    if (_camera)
    {
        _camera->drop();
        _camera = NULL;
    }
 
    if (_refractionMap)
    {
        _refractionMap->drop();
        _refractionMap = NULL;
    }
 
    if (_reflectionMap)
    {
        _reflectionMap->drop();
        _reflectionMap = NULL;
    }
 
    if (_waterSceneNode)
    {
        _waterSceneNode->drop();
        _waterSceneNode = NULL;
    }
 
    if (_waterMesh)
    {
        _waterMesh->drop();
        _waterMesh = NULL;
    }
}
 
// frame
void RealisticWaterSceneNode::OnRegisterSceneNode()
{
    ISceneNode::OnRegisterSceneNode();
 
    if (IsVisible)
    {
        _sceneManager->registerNodeForRendering(this);
    }
}
 
void RealisticWaterSceneNode::OnAnimate(u32 timeMs)
{
    ISceneNode::OnAnimate(timeMs);
 
    _time = timeMs;
 
    //fixes glitches with incomplete refraction
    const f32 CLIP_PLANE_OFFSET_Y = 5.0f;
 
    if (IsVisible)
    {
        setVisible(false); //hide the water
 
        //refraction
        _videoDriver->setRenderTarget(_refractionMap, true, true); //render to refraction
 
        //refraction clipping plane
        core::plane3d<f32> refractionClipPlane(0, RelativeTranslation.Y + CLIP_PLANE_OFFSET_Y, 0, 0, -1, 0); //refraction clip plane
        _videoDriver->setClipPlane(0, refractionClipPlane, true);
 
        _sceneManager->drawAll(); //draw the scene
 
        //reflection
        _videoDriver->setRenderTarget(_reflectionMap, true, true); //render to reflection
 
        //get current camera
        scene::ICameraSceneNode* currentCamera = _sceneManager->getActiveCamera();
 
        //set FOV anf far value from current camera
        _camera->setFarValue(currentCamera->getFarValue());
        _camera->setFOV(currentCamera->getFOV());
 
        core::vector3df position = currentCamera->getAbsolutePosition();
        position.Y = -position.Y + 2 * RelativeTranslation.Y; //position of the water
        _camera->setPosition(position);
 
        core::vector3df target = currentCamera->getTarget();
 
        //invert Y position of current camera
        target.Y = -target.Y + 2 * RelativeTranslation.Y;
        _camera->setTarget(target);
 
        //set the reflection camera
        _sceneManager->setActiveCamera(_camera);
 
        //reflection clipping plane
        core::plane3d<f32> reflectionClipPlane(0, RelativeTranslation.Y - CLIP_PLANE_OFFSET_Y, 0, 0, 1, 0);
        _videoDriver->setClipPlane(0, reflectionClipPlane, true);
 
        _sceneManager->drawAll(); //draw the scene
 
        //disable clip plane
        _videoDriver->enableClipPlane(0, false);
 
        //set back old render target
        _videoDriver->setRenderTarget(0, false, true);
 
        //set back the active camera
        _sceneManager->setActiveCamera(currentCamera);
 
        setVisible(true); //show it again
    }
}
 
void RealisticWaterSceneNode::render()
{
    /*core::array<video::IRenderTarget> renderTargets;
    //renderTargets.push_back();
    renderTargets.push_back(_refractionMap);
 
    _videoDriver->setRenderTarget(renderTargets, true, true);*/
    //_videoDriver->draw2DImage(_reflectionMap,core::position2d<s32>(0,0));
}
 
// returns the axis aligned bounding box of terrain
const core::aabbox3d<f32>& RealisticWaterSceneNode::getBoundingBox() const
{
    return _waterSceneNode->getBoundingBox();
}
 
void RealisticWaterSceneNode::OnSetConstants(video::IMaterialRendererServices* services, s32 userData)
{
    video::IVideoDriver* driver = services->getVideoDriver();
 
    core::matrix4 projection = driver->getTransform(video::ETS_PROJECTION);
    core::matrix4 view = driver->getTransform(video::ETS_VIEW);
    core::matrix4 world = driver->getTransform(video::ETS_WORLD);
 
    core::matrix4 cameraView = _camera->getViewMatrix();
 
    //vertex shader constants
    //services->setVertexShaderConstant("View", view.pointer(), 16);
    
    core::matrix4 worldViewProj = projection;           
    worldViewProj *= view;
    worldViewProj *= world;
    
    core::matrix4 worldReflectionViewProj = projection;
    worldReflectionViewProj *= cameraView;
    worldReflectionViewProj *= world;
    
    f32 waveLength = 0.1f;
    f32 time = _time / 100000.0f;
    core::vector3df cameraPosition = _sceneManager->getActiveCamera()->getPosition();
    
    bool fogEnabled = getMaterial(0).getFlag(video::EMF_FOG_ENABLE);
    irr::video::SColor color;
    irr::video::E_FOG_TYPE fogType;
    f32 start;
    f32 end;
    f32 density;
    bool pixelFog;
    bool rangeFog;
    driver->getFog(color, fogType, start, end, density, pixelFog, rangeFog);
    
#if (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR == 9)
    services->setVertexShaderConstant(services->getVertexShaderConstantID("WorldViewProj"), worldViewProj.pointer(), 16);
    services->setVertexShaderConstant(services->getVertexShaderConstantID("WorldReflectionViewProj"), worldReflectionViewProj.pointer(), 16);
    services->setVertexShaderConstant(services->getVertexShaderConstantID("WaveLength"), &waveLength, 1);
    services->setVertexShaderConstant(services->getVertexShaderConstantID("Time"), &time, 1);
    services->setVertexShaderConstant(services->getVertexShaderConstantID("WindForce"), &_windForce, 1);
    services->setVertexShaderConstant(services->getVertexShaderConstantID("WindDirection"), &_windDirection.X, 2);
    services->setPixelShaderConstant(services->getVertexShaderConstantID("CameraPosition"), &cameraPosition.X, 3);
    services->setPixelShaderConstant(services->getVertexShaderConstantID("WaveHeight"), &_waveHeight, 1);
    services->setPixelShaderConstant(services->getVertexShaderConstantID("WaterColor"), &_waterColor.r, 4);
    services->setPixelShaderConstant(services->getVertexShaderConstantID("ColorBlendFactor"), &_colorBlendFactor, 1);
#else
    services->setVertexShaderConstant("WorldViewProj", worldViewProj.pointer(), 16);
    services->setVertexShaderConstant("WorldReflectionViewProj", worldReflectionViewProj.pointer(), 16);
    services->setVertexShaderConstant("WaveLength", &waveLength, 1);
    services->setVertexShaderConstant("Time", &time, 1);
    services->setVertexShaderConstant("WindForce", &_windForce, 1);
    services->setVertexShaderConstant("WindDirection", &_windDirection.X, 2);
    services->setPixelShaderConstant("CameraPosition", &cameraPosition.X, 3);
    services->setPixelShaderConstant("WaveHeight", &_waveHeight, 1);
    services->setPixelShaderConstant("WaterColor", &_waterColor.r, 4);
    services->setPixelShaderConstant("ColorBlendFactor", &_colorBlendFactor, 1);
#endif
    
    //texture constants for GLSL
    if (driver->getDriverType() == video::EDT_OPENGL)
    {
        int var0 = 0;
        int var1 = 1;
        int var2 = 2;
        
#if (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR == 9)
        services->setPixelShaderConstant(services->getVertexShaderConstantID("WaterBump"), &var0, 1);
        services->setPixelShaderConstant(services->getVertexShaderConstantID("RefractionMap"), &var1, 1);
        services->setPixelShaderConstant(services->getVertexShaderConstantID("ReflectionMap"), &var2, 1);
        
        services->setPixelShaderConstant(services->getVertexShaderConstantID("FogEnabled"), (int*)&fogEnabled, 1);
        services->setPixelShaderConstant(services->getVertexShaderConstantID("FogMode"), (int*)&fogType, 1);
#else
        services->setPixelShaderConstant("WaterBump", &var0, 1);
        services->setPixelShaderConstant("RefractionMap", &var1, 1);
        services->setPixelShaderConstant("ReflectionMap", &var2, 1);
        
        services->setPixelShaderConstant("FogEnabled", (int*)&fogEnabled, 1);
        services->setPixelShaderConstant("FogMode", (int*)&fogType, 1);
#endif
    }
}
 
void RealisticWaterSceneNode::setWindForce(const f32 windForce)
{
    _windForce = windForce;
}
 
void RealisticWaterSceneNode::setWindDirection(const core::vector2df& windDirection)
{
    _windDirection = windDirection;
    _windDirection.normalize();
}
 
void RealisticWaterSceneNode::setWaveHeight(const f32 waveHeight)
{
    _waveHeight = waveHeight;
}
 
void RealisticWaterSceneNode::setWaterColor(const video::SColorf& waterColor)
{
    _waterColor = waterColor;
}
 
void RealisticWaterSceneNode::setColorBlendFactor(const f32 colorBlendFactor)
{
    _colorBlendFactor = colorBlendFactor;
}
 
//shaders

Code: Select all

 
/*
 * Copyright (c) 2013, elvman
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY elvman ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL elvman BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
//uniform mat4  View;
uniform mat4    WorldViewProj;  // World * View * Projection transformation
uniform mat4    WorldReflectionViewProj;  // World * Reflection View * Projection transformation
 
uniform float   WaveLength;
 
uniform float   Time;
uniform float   WindForce;
uniform vec2    WindDirection;
 
// Vertex shader output structure
varying vec2 bumpMapTexCoord;
varying vec3 refractionMapTexCoord;
varying vec3 reflectionMapTexCoord;
varying vec3 position3D;
 
void main()
{
    //color = gl_Color;
 
    // transform position to clip space
    vec4 pos = WorldViewProj * gl_Vertex;
    gl_Position = pos;
    
    // calculate vawe coords
    bumpMapTexCoord = gl_MultiTexCoord0.xy / WaveLength + Time * WindForce * WindDirection;
 
    // refraction texcoords
    refractionMapTexCoord.x = 0.5 * (pos.w + pos.x);
    refractionMapTexCoord.y = 0.5 * (pos.w + pos.y);
    refractionMapTexCoord.z = pos.w;
                                
    // reflection texcoords
    pos = WorldReflectionViewProj * gl_Vertex;
    reflectionMapTexCoord.x = 0.5 * (pos.w + pos.x);
    reflectionMapTexCoord.y = 0.5 * (pos.w + pos.y);
    reflectionMapTexCoord.z = pos.w;
    
    // position of the vertex
    position3D = gl_Vertex.xyz;
}
 

Code: Select all

 
/*
 * Copyright (c) 2013, elvman
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY elvman ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL elvman BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
const float LOG2 = 1.442695;
 
uniform vec3        CameraPosition;  // Position of main position
uniform float       WaveHeight;
 
uniform vec4        WaterColor;
uniform float       ColorBlendFactor;
 
uniform sampler2D   WaterBump; //coverage
uniform sampler2D   RefractionMap; //coverage
uniform sampler2D   ReflectionMap; //coverage
 
uniform bool        FogEnabled;
uniform int         FogMode;
 
varying vec2 bumpMapTexCoord;
varying vec3 refractionMapTexCoord;
varying vec3 reflectionMapTexCoord;
varying vec3 position3D;
    
void main()
{
    //bump color
    vec4 bumpColor = texture2D(WaterBump, bumpMapTexCoord);
    vec2 perturbation = WaveHeight * (bumpColor.rg - 0.5);
    
    //refraction
    vec2 ProjectedRefractionTexCoords = clamp(refractionMapTexCoord.xy / refractionMapTexCoord.z + perturbation, 0.0, 1.0);
    //calculate final refraction color
    vec4 refractiveColor = texture2D(RefractionMap, ProjectedRefractionTexCoords );
    
    //reflection
    vec2 ProjectedReflectionTexCoords = clamp(reflectionMapTexCoord.xy / reflectionMapTexCoord.z + perturbation, 0.0, 1.0);
    //calculate final reflection color
    vec4 reflectiveColor = texture2D(ReflectionMap, ProjectedReflectionTexCoords );
 
    //fresnel
    vec3 eyeVector = normalize(CameraPosition - position3D);
    vec3 upVector = vec3(0.0, 1.0, 0.0);
    
    //fresnel can not be lower than 0
    float fresnelTerm = max( dot(eyeVector, upVector), 0.0 );
    
    float fogFactor = 1.0;
    
    if (FogEnabled)
    {
        float z = gl_FragCoord.z / gl_FragCoord.w;
 
        if (FogMode == 1) //exp
        {
            float fogFactor = exp2(-gl_Fog.density * z * LOG2);
            fogFactor = clamp(fogFactor, 0.0, 1.0);
        }
        else if (FogMode == 0) //linear
        {
            fogFactor = (gl_Fog.end - z) / (gl_Fog.end - gl_Fog.start);
        }
        else if (FogMode == 2) //exp2
        {
            float fogFactor = exp2(-gl_Fog.density * gl_Fog.density * z * z * LOG2);
            fogFactor = clamp(fogFactor, 0.0, 1.0);
        }
    }
    
    vec4 combinedColor = refractiveColor * fresnelTerm + reflectiveColor * (1.0 - fresnelTerm);
    
    vec4 finalColor = ColorBlendFactor * WaterColor + (1.0 - ColorBlendFactor) * combinedColor;
    
    gl_FragColor = mix(gl_Fog.color, finalColor, fogFactor );
}
 
 
Mars_999
Posts: 136
Joined: Sat Dec 08, 2012 7:59 pm

Re: Realistic water scene node

Post by Mars_999 »

RealisticWaterSceneNode* water = new RealisticWaterSceneNode(smgr,
4096, 4096,
"C:/Programming/Work/TBSG/TBSG",
irr::core::dimension2du(4096, 4096),
smgr->getRootSceneNode());

fixed it! for some reason I needed to getRootSeneNode() vs. nullptr or 0... odd

but I am getting black artifacts in the final image? what would that be?

Image
thanhle
Posts: 325
Joined: Wed Jun 12, 2013 8:09 am

Re: Realistic water scene node

Post by thanhle »

Maybe increase your skybox size?
I think those shadow appears when the water scenenode reaches the border of your skybox.
Mars_999
Posts: 136
Joined: Sat Dec 08, 2012 7:59 pm

Re: Realistic water scene node

Post by Mars_999 »

nope it's a y clip plane problem. I fixed it. Please put that as a parameter to the constructor of this great little scene node!
Christi258
Posts: 62
Joined: Wed Feb 06, 2013 12:11 pm

Re: Realistic water scene node

Post by Christi258 »

Very Good Project!!!
But the refrection doesn't work that well!!
I think thats the reason why it doesn't look that realistic.
Do you still work on this project elvman?
elvman
Posts: 253
Joined: Sun Sep 17, 2006 9:37 am
Location: Riga, Latvia
Contact:

Re: Realistic water scene node

Post by elvman »

What is the problem with refraction? Yes, I still work on it.
Ouzel – 2D game engine
Realistic water node
Christi258
Posts: 62
Joined: Wed Feb 06, 2013 12:11 pm

Re: Realistic water scene node

Post by Christi258 »

Sorry, there seems to be a problem with refrection if you set as parent node any SceneNode instead of SceneManager->getRootSceneNode().
Do you have any updates?

EDIT: With a high distance the reflexion disappears. Why?
Post Reply