Ways of splitscreen with water scene node [SOLVED]

You are an experienced programmer and have a problem with the engine, shaders, or advanced effects? Here you'll get answers.
No questions about C++ programming or topics which are answered in the tutorials!
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Depends on what render target is current at that moment. Still, seeing some code would probably solve this in minutes, not weeks.
devsh
Competition winner
Posts: 2049
Joined: Tue Dec 09, 2008 6:00 pm
Location: UK
Contact:

Post by devsh »

because you think its necessary

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();

}
Main.cpp

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();
   }
}
This creates this
Image

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:

Post by hybrid »

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).
devsh
Competition winner
Posts: 2049
Joined: Tue Dec 09, 2008 6:00 pm
Location: UK
Contact:

Post by devsh »

do you know what
there is a function of the driver that writes an Image(texture) to file, so i will check if the reflections and refractions are rendered ok for each, and if the offset reflection is the fault of the shader.
devsh
Competition winner
Posts: 2049
Joined: Tue Dec 09, 2008 6:00 pm
Location: UK
Contact:

Post by devsh »

how to convert a ITexture to IImage???
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

lock texture, create image from data, unlock.
zillion42
Posts: 324
Joined: Wed Aug 29, 2007 12:32 am
Location: Hamburg, Germany

Post by zillion42 »

Except for the aspect ratio of the splitsreen cam it looks good...

is that really 2 frames per second or is you screenshot somehow wrong ?
devsh
Competition winner
Posts: 2049
Joined: Tue Dec 09, 2008 6:00 pm
Location: UK
Contact:

Post by devsh »

Its Yield if the window is not active it stops rendering but i get around 54fps

And yes i would like to fix the stretching issue, but i fix my reflections first
devsh
Competition winner
Posts: 2049
Joined: Tue Dec 09, 2008 6:00 pm
Location: UK
Contact:

Post by devsh »

create image from data??? WTF??
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

The method has exactly that name. What problem do you have?
devsh
Competition winner
Posts: 2049
Joined: Tue Dec 09, 2008 6:00 pm
Location: UK
Contact:

Post by devsh »

ok got it!!

It was because my second camera had a parent!

so now it copies the reflection camera by getting the absolute position and not the relative position.
Post Reply