Ways of splitscreen with water scene node [SOLVED]
because you think its necessary
NOTE: device pointer is global
RealisticWater.h
Main.cpp
This creates this

P.S. You probably cant see it now but when i pull reflectivity to 90%, you can see it more clearly. The thing is that the reflection in the bottom camera is basically "gently caressed".
NOTE: device pointer is global
RealisticWater.h
Code: Select all
/*
* Copyright (c) 2007, 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.
*/
#pragma once
#include <string>
#include <irrlicht.h>
#include "thread.h"
class RealisticWaterSceneNode: public irr::scene::ISceneNode, irr::video::IShaderConstantSetCallBack
{
public:
RealisticWaterSceneNode(irr::f32 width, irr::f32 height, irr::video::ITexture* bumpTexture, irr::ITimer* timer, irr::core::dimension2di renderTargetSize=irr::core::dimension2di(512,512),irr::scene::ISceneNode* parent = 0, irr::s32 id = -1);
virtual ~RealisticWaterSceneNode();
// frame
virtual void OnRegisterSceneNode();
virtual void OnAnimate(irr::u32 timeMs, int camorder);
// renders terrain
virtual void render();
virtual const irr::core::aabbox3d<irr::f32>& getBoundingBox() const {return WaterSceneNode->getBoundingBox();}
virtual void OnSetConstants(irr::video::IMaterialRendererServices* services, irr::s32 userData);
virtual void setWindForce(const irr::f32 windForce) {WindForce=windForce;}
virtual void setWindDirection(const irr::core::vector2df& windDirection);
virtual void setWaveHeight(const irr::f32 waveHeight) {WaveHeight=waveHeight;}
virtual void setWaterColor(const irr::video::SColorf& waterColor) {WaterColor=waterColor;}
virtual void setColorBlendFactor(const irr::f32 colorBlendFactor) {ColorBlendFactor=colorBlendFactor;}
virtual void setReflectivity(const irr::f32 reflectiv) {reflectivity=reflectiv;}
virtual irr::f32 getWindForce() {return WindForce;}
virtual irr::core::vector2df getWindDirection() {return WindDirection;};
virtual irr::f32 getWaveHeight() {return WaveHeight;}
virtual irr::video::SColorf getWaterColor() {return WaterColor;}
virtual irr::f32 getColorBlendFactor() {return ColorBlendFactor;}
virtual irr::f32 getReflectivity() {return reflectivity;}
virtual irr::core::dimension2df getSize() {return Size;}
private:
irr::scene::ICameraSceneNode* Camera;
irr::scene::ICameraSceneNode* CurrentCamera;
irr::scene::IMesh* WaterMesh;
irr::scene::ISceneNode* WaterSceneNode;
irr::core::vector3df positionOA;
irr::core::vector3df targetOA;
irr::video::IVideoDriver* VideoDriver;
irr::ITimer* Timer;
irr::core::dimension2d<irr::f32> Size;
irr::s32 ShaderMaterial;
irr::video::ITexture* RefractionMap;
irr::video::ITexture* ReflectionMap;
irr::f32 WindForce;
irr::core::vector2df WindDirection;
irr::f32 WaveHeight;
irr::video::SColorf WaterColor;
irr::f32 ColorBlendFactor;
irr::f32 reflectivity;
};
RealisticWaterSceneNode::RealisticWaterSceneNode(irr::f32 width, irr::f32 height, irr::video::ITexture* bumpTexture, irr::ITimer* timer, irr::core::dimension2di renderTargetSize, irr::scene::ISceneNode* parent, irr::s32 id) : irr::scene::ISceneNode( parent, device->getSceneManager(), id) {
Timer = timer;
Size = irr::core::dimension2d<irr::f32>(width,height);
RefractionMap=NULL;
ReflectionMap=NULL;
reflectivity=0.25;
WindForce = 20.0f;
WindDirection = irr::core::vector2df(0,1);
WaveHeight =0.3f;
WaterColor= irr::video::SColorf(0.1f, 0.1f, 0.6f, 1.0f);
ColorBlendFactor=0.2f;
Camera=NULL;
VideoDriver = device->getSceneManager()->getVideoDriver();
CurrentCamera= device->getSceneManager()->getActiveCamera(); //get current camera
Camera=device->getSceneManager()->addCameraSceneNode(); //create new camera
device->getSceneManager()->setActiveCamera(CurrentCamera); //set back the previous camera
WaterMesh = device->getSceneManager()->addHillPlaneMesh("realisticwater",Size,irr::core::dimension2d<irr::u32>(1,1));
WaterMesh->setHardwareMappingHint(irr::scene::EHM_STATIC);
WaterSceneNode=SceneManager->addMeshSceneNode(WaterMesh,this);
irr::video::IGPUProgrammingServices* GPUProgrammingServices = VideoDriver->getGPUProgrammingServices();
std::string WaterPixelShader="shaders/Water_ps.glsl";
std::string WaterVertexShader="shaders/Water_vs.glsl";
ShaderMaterial=GPUProgrammingServices->addHighLevelShaderMaterialFromFiles( WaterVertexShader.c_str(),"main",irr::video::EVST_VS_1_1, WaterPixelShader.c_str(), "main",irr::video::EPST_PS_2_0, this,irr::video::EMT_LIGHTMAP);
WaterSceneNode->setMaterialType((irr::video::E_MATERIAL_TYPE)ShaderMaterial);
WaterSceneNode->setMaterialTexture(0,bumpTexture);
RefractionMap=VideoDriver->createRenderTargetTexture(renderTargetSize);
ReflectionMap=VideoDriver->createRenderTargetTexture(renderTargetSize);
WaterSceneNode->setMaterialTexture(1,RefractionMap);
WaterSceneNode->setMaterialTexture(2,ReflectionMap);
}
RealisticWaterSceneNode::~RealisticWaterSceneNode()
{
Camera->drop();
if (RefractionMap) RefractionMap->drop();
if (ReflectionMap) ReflectionMap->drop();
}
// frame
void RealisticWaterSceneNode::OnRegisterSceneNode()
{
if (IsVisible)
SceneManager->registerNodeForRendering(this);
ISceneNode::OnRegisterSceneNode();
}
void RealisticWaterSceneNode::OnAnimate(irr::u32 timeMs, int camorder)
{
if (IsVisible) {
setVisible(false);
VideoDriver->setRenderTarget(RefractionMap, true, true, irr::video::SColor(255,0,0,0)); //render to refraction
device->getSceneManager()->drawAll();
VideoDriver->setRenderTarget(ReflectionMap, true, true, irr::video::SColor(255,0,0,0)); //render to reflection
irr::scene::ICameraSceneNode* CurrentCamera=SceneManager->getActiveCamera(); //get current camera
// Added by Christian Clavet to update the camera FOV (Zooming)
Camera->setFarValue(CurrentCamera->getFarValue());
Camera->setFOV(CurrentCamera->getFOV());
positionOA=CurrentCamera->getPosition();
positionOA.Y=-positionOA.Y+2*RelativeTranslation.Y; //position of the water
Camera->setPosition(positionOA);
targetOA=CurrentCamera->getTarget();
targetOA.Y=-targetOA.Y+2*RelativeTranslation.Y;
Camera->setTarget(targetOA);
SceneManager->setActiveCamera(Camera); //set the reflection camera
SceneManager->drawAll(); //draw the scene
SceneManager->setActiveCamera(CurrentCamera);
VideoDriver->setRenderTarget(0,false,true);
setVisible(true); //show it again
}
ISceneNode::OnAnimate(timeMs);
}
void RealisticWaterSceneNode::render() {
VideoDriver->setMaterial(WaterSceneNode->getMaterial(0));
irr::core::matrix4 Mat;
Mat.makeIdentity();
//On sauvegarde les matrices
irr::core::matrix4 MatrixWorld = VideoDriver->getTransform(irr::video::ETS_WORLD);
irr::core::matrix4 MatrixView = VideoDriver->getTransform(irr::video::ETS_VIEW);
//On applique les matrices de monde et de vue
VideoDriver->setTransform(irr::video::ETS_WORLD, AbsoluteTransformation);
VideoDriver->setTransform(irr::video::ETS_VIEW,Mat);
//On dessine nos Quad ici
VideoDriver->drawMeshBuffer(WaterMesh->getMeshBuffer(0));
//On restaure les matrices
VideoDriver->setTransform(irr::video::ETS_VIEW,MatrixView);
VideoDriver->setTransform(irr::video::ETS_WORLD,MatrixWorld);
}
void RealisticWaterSceneNode::OnSetConstants(irr::video::IMaterialRendererServices* services, irr::s32 userData)
{
irr::core::matrix4 view = VideoDriver->getTransform(irr::video::ETS_VIEW);
services->setVertexShaderConstant("View", view.pointer(), 16);
//vertex shader constants
irr::core::matrix4 worldViewProj = VideoDriver->getTransform(irr::video::ETS_PROJECTION);
worldViewProj *= VideoDriver->getTransform(irr::video::ETS_VIEW);
worldViewProj *= VideoDriver->getTransform(irr::video::ETS_WORLD);
services->setVertexShaderConstant("WorldViewProj", worldViewProj.pointer(), 16);
irr::core::matrix4 worldReflectionViewProj=VideoDriver->getTransform(irr::video::ETS_PROJECTION);
worldReflectionViewProj *= Camera->getViewMatrix();
worldReflectionViewProj *= VideoDriver->getTransform(irr::video::ETS_WORLD);
services->setVertexShaderConstant("WorldReflectionViewProj", worldReflectionViewProj.pointer(), 16);
irr::f32 WaveLength=0.1f;
services->setVertexShaderConstant("WaveLength", &WaveLength, 1);
irr::f32 time=Timer->getTime()/100000.0f;
services->setVertexShaderConstant("Time", &time, 1);
services->setVertexShaderConstant("WindForce", &WindForce, 1);
services->setVertexShaderConstant("WindDirection", &WindDirection.X, 2);
//pixel shader constants
irr::core::vector3df CameraPosition = SceneManager->getActiveCamera()->getPosition();
services->setPixelShaderConstant("CameraPosition", &CameraPosition.X, 3);
services->setPixelShaderConstant("WaveHeight", &WaveHeight, 1);
services->setPixelShaderConstant("reflectivity", &reflectivity, 1);
services->setPixelShaderConstant("WaterColor", &WaterColor.r, 4);
services->setPixelShaderConstant("ColorBlendFactor", &ColorBlendFactor, 1);
int d[] = { 0,1,2 }; // sampler2d IDs
services->setPixelShaderConstant("WaterBump", (float*)&d[0], 1);
services->setPixelShaderConstant("RefractionMap", (float*)&d[1], 1);
services->setPixelShaderConstant("ReflectionMap", (float*)&d[2], 1);
}
void RealisticWaterSceneNode::setWindDirection(const irr::core::vector2df& windDirection)
{
WindDirection=windDirection;
WindDirection.normalize();
}Code: Select all
//3ds, b3d A, X A, ms3d A, oct L and lmts L
/*=====================================
CREDITS
PROGRAMMER MATTHEW KIELAN, DEVUSH, DEVSH OR EDUARDO
REALISTIC WATER SCENE NODE by elvman
Thank you hybrid without you i would never do split screen
=======================================*/
#include "RealisticWater.h"
void SinglePlayerLoop(irr::scene::ICameraSceneNode* camera, RealisticWaterSceneNode* Water);
void SplitScreenLoop(irr::scene::ICameraSceneNode* cam1,irr::scene::ICameraSceneNode* cam2, RealisticWaterSceneNode* Water);
int main(int argc, const char** argv) {
device = irr::createDevice( irr::video::EDT_OPENGL, irr::core::dimension2d<irr::s32>(res.x, res.y), 32, false, stencilbuffer, true, &Keyboard);
if (!device) {
std::cout << "Error 3: Graphical display initialisation failed" << std::endl;
return 1;
}
device->getFileSystem()->addZipFileArchive("./Game Data/data20080511.pk3");
qmapmesh = device->getSceneManager()->getMesh("./Game Data/data20080511.pk3/maps/ruiner.bsp");
qmapmesh->setHardwareMappingHint(irr::scene::EHM_STATIC);
device->getCursorControl()->setVisible(false);
device->setWindowCaption(L"Project Ninja Star");
loadjoy();
joystick1 = new joystick(jdf, Gamepad, rdf);
if (!joystick1)
joystick1 = new joystick("/dev/input/js0", Gamepad, "/dev/input/event6");
player* player1 = make_player (device);
player* player2 = make_player (device, false, "./media/ninja.b3d", player1, irr::core::vector3df(-650,-528,-300) , joystick1);
player2->getnode()->setFrameLoop(184, 205);
player2->getnode()->setAnimationSpeed(8);
player2->getnode()->setScale(irr::core::vector3df(12.0f));
if (!player1->getmesh()) {
std::cout << "Error 4: Could not load player mesh" << std::endl;
}
if (!player2->getmesh()) {
std::cout << "Error 4: Could not load player mesh" << std::endl;
}
qmapnode = device->getSceneManager()->addMeshSceneNode(qmapmesh->getMesh(0));
qmapnode->setPosition(irr::core::vector3df(-1300,-144,-1249));
irr::scene::ICameraSceneNode* camera[2]={device->getSceneManager()->addCameraSceneNodeFPS(), device->getSceneManager()->addCameraSceneNode(player2->getnode(), irr::core::vector3df(0,12,-10), irr::core::vector3df(player2->getnode()->getPosition().X,player2->getnode()->getPosition().Y,player2->getnode()->getPosition().Z+50))};
irr::video::IVideoDriver* driver = device->getSceneManager()->getVideoDriver();
irr::scene::ISceneManager* smgr = device->getSceneManager();
irr::gui::IGUIEnvironment* guienv = device->getGUIEnvironment();
RealisticWaterSceneNode* Water=new RealisticWaterSceneNode(1228,1640, driver->getTexture("./waterbump.png"),device->getTimer());
Water->setPosition(irr::core::vector3df(-1146,-510,-652));
Water->setWaterColor(irr::video::SColor(0.1f, 0.1f, 0.6f, 1.0f));
Water->setWindForce(10.0f);
Water->setReflectivity(0.9f);
if (splitscreen) SplitScreenLoop(camera[0],camera[1],Water);
else SinglePlayerLoop(camera[0],Water);
device->drop();
savejoy(player2->getJoystick());
return 0;
}
void SplitScreenLoop(irr::scene::ICameraSceneNode* cam1,irr::scene::ICameraSceneNode* cam2, RealisticWaterSceneNode* Water) {
int lastFPS = -1;
int fps;
irr::video::IVideoDriver* driver = device->getSceneManager()->getVideoDriver();
irr::scene::ISceneManager* smgr = device->getSceneManager();
while (device->run()) {
if (device->isWindowActive()) {
driver->beginScene(false, true);
smgr->setActiveCamera(cam2);
driver->setViewPort(irr::core::rect<irr::s32>(0,(res.y/2),res.x,res.y));
if (cam2->getPosition().Y>=Water->getAbsolutePosition().Y) {
Water->OnAnimate(device->getTimer()->getTime(),2);
driver->setViewPort(irr::core::rect<irr::s32>(0,(res.y/2),res.x,res.y));
Water->OnRegisterSceneNode();
Water->render();
driver->setViewPort(irr::core::rect<irr::s32>(0,(res.y/2),res.x,res.y));
}
smgr->drawAll();
driver->endScene();
driver->beginScene(false, true, irr::video::SColor(0,0,0,0));
smgr->setActiveCamera(cam1);
driver->setViewPort(irr::core::rect<irr::s32>(0,0,res.x,(res.y/2)));
if (cam1->getPosition().Y>=Water->getAbsolutePosition().Y) {
Water->OnAnimate(device->getTimer()->getTime(),1);
driver->setViewPort(irr::core::rect<irr::s32>(0,0,res.x,(res.y/2)));
Water->OnRegisterSceneNode();
Water->render();
driver->setViewPort(irr::core::rect<irr::s32>(0,0,res.x,(res.y/2)));
}
smgr->drawAll();
driver->endScene();
//driver->clearBackBuffer(); This is the type of thing i'm looking for
fps = driver->getFPS();
if (lastFPS != fps) {
irr::core::stringw str = L"Project Ninja Star - Nexuiz Map example FPS:";
str += fps;
device->setWindowCaption(str.c_str());
lastFPS = fps;
}
}
else
device->yield();
}
}
void SinglePlayerLoop(irr::scene::ICameraSceneNode* camera, RealisticWaterSceneNode* Water) {
int lastFPS = -1;
int fps;
irr::video::IVideoDriver* driver = device->getSceneManager()->getVideoDriver();
irr::scene::ISceneManager* smgr = device->getSceneManager();
driver->setViewPort(irr::core::rect<irr::s32>(0,0,res.x,res.y));
smgr->setActiveCamera(camera);
while (device->run()) {
if (device->isWindowActive()) {
driver->beginScene(true, true, irr::video::SColor(255,0,0,0));
if (camera->getPosition().Y>=Water->getAbsolutePosition().Y) {
Water->OnAnimate(device->getTimer()->getTime(),0);
Water->OnRegisterSceneNode();
Water->render();
}
smgr->drawAll();
driver->endScene();
fps = driver->getFPS();
if (lastFPS != fps) {
irr::core::stringw str = L"Project Ninja Star - Nexuiz Map example FPS:";
str += fps;
device->setWindowCaption(str.c_str());
lastFPS = fps;
}
}
else
device->yield();
}
}
P.S. You probably cant see it now but when i pull reflectivity to 90%, you can see it more clearly. The thing is that the reflection in the bottom camera is basically "gently caressed".
-
hybrid
- Admin
- Posts: 14143
- Joined: Wed Apr 19, 2006 9:20 pm
- Location: Oldenburg(Oldb), Germany
- Contact:
Your camera might have a wrong aspect ratio (due to the splitting). Moreover, there's also some buffer clearing in the water node. So just make sure it does the necessary stuff. Furthermore, the water node seems to require some rendering on the main buffer, so make sure the shaders can cope with half screen processing. Also check which parts are really required in the water node, and which parts must render where (such that you can clean up your clearing calls).