I dont understand the fov of the camera working at 0.93, I just changed it til it looked right.
the idea is, of course, to render lots of distant terrain/mesh/etc into the skybox outside your main loop, and render the skybox each frame instead
Code: Select all
// CRTTSkyBox.h
#ifndef __C_RTT_SKY_BOX_SCENE_NODE_H_INCLUDED__
#define __C_RTT_SKY_BOX_SCENE_NODE_H_INCLUDED__
#include "ISceneNode.h"
#include "ICameraSceneNode.h"
#include "S3DVertex.h"
namespace irr
{
namespace scene
{
// Skybox, rendererd with zbuffer turned off, before all other nodes.
class CRTTSkyBoxSceneNode : public ISceneNode
{
public:
//! constructor
CRTTSkyBoxSceneNode(core::dimension2d<s32> size, ISceneNode* parent, ISceneManager* mgr, s32 id);
//! destructor
virtual ~CRTTSkyBoxSceneNode();
// renders the view from the said position to the skybox
void renderToSkyBox(core::vector3df pos, video::SColor col=video::SColor(0,0,0,255), bool self=false);
virtual void OnPreRender();
//! renders the node.
virtual void render();
//! returns the axis aligned bounding box of this node
virtual const core::aabbox3d<f32>& getBoundingBox() const;
//! returns the material based on the zero based index i. To get the amount
//! of materials used by this scene node, use getMaterialCount().
//! This function is needed for inserting the node into the scene hirachy on a
//! optimal position for minimizing renderstate changes, but can also be used
//! to directly modify the material of a scene node.
virtual video::SMaterial& getMaterial(s32 i);
//! returns amount of materials used by this scene node.
virtual s32 getMaterialCount();
scene::ICameraSceneNode *skyCam;
private:
core::aabbox3d<f32> Box;
u16 Indices[6];
video::S3DVertex Vertices[4*6];
video::SMaterial Material[6];
video::ITexture *rt[6];
};
} // end namespace scene
} // end namespace irr
#endif
Code: Select all
// Copyright (C) 2002-2005 Nikolaus Gebhardt
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#include "CRTTSkyBoxSceneNode.h"
#include "IVideoDriver.h"
#include "ISceneManager.h"
#include "ICameraSceneNode.h"
#include "S3DVertex.h"
namespace irr
{
namespace scene
{
//! constructor
CRTTSkyBoxSceneNode::CRTTSkyBoxSceneNode(core::dimension2d<s32> size, ISceneNode* parent, ISceneManager* mgr, s32 id)
: ISceneNode(parent, mgr, id)
{
#ifdef _DEBUG
setDebugName("CRTTSkyBoxSceneNode");
#endif
AutomaticCullingEnabled = false;
// create indices
Indices[0] = 0;
Indices[1] = 1;
Indices[2] = 2;
Indices[3] = 0;
Indices[4] = 2;
Indices[5] = 3;
// create material
video::SMaterial mat;
mat.Lighting = false;
mat.ZBuffer = false;
mat.ZWriteEnable = false;
mat.BilinearFilter = true;
/* Hey, I am no artist, but look at that
cool ASCII art I made! ;) (Niko)
-111 111
/6--------/5 y
/ | / | ^ z
/ | 11-1 | | /
-11-1 3---------2 | |/
| 7- - -| -4 1-11 *---->x
| -1-11 | / 3-------|2
|/ | / | //|
0---------1/ | // |
-1-1-1 1-1-1 |// |
0--------1
*/
f32 onepixel = 1.0f / (size.Width * 1.5f);
// create the render targets
for (s32 n=0; n<6; ++n)
rt[n] = mgr->getVideoDriver()->createRenderTargetTexture(size);
// create camera (remember last camera)
scene::ICameraSceneNode *currentcam = mgr->getActiveCamera();
skyCam = mgr->addCameraSceneNode();
skyCam->setFarValue(100000.0f);
skyCam->setAspectRatio(1.0f);
skyCam->setFOV(0.93f); // dunno why, but it works here
mgr->setActiveCamera(currentcam);
f32 l = 10.0f;
f32 t = 1.0f - onepixel;
f32 o = 0.0f + onepixel;
Material[0] = mat;
Material[0].Texture1 = rt[4];
Vertices[0] = video::S3DVertex(-l,-l,-l, 0,0,1, video::SColor(255,255,255,255), t, o);
Vertices[1] = video::S3DVertex( l,-l,-l, 0,0,1, video::SColor(255,255,255,255), o, o);
Vertices[2] = video::S3DVertex( l, l,-l, 0,0,1, video::SColor(255,255,255,255), o, t);
Vertices[3] = video::S3DVertex(-l, l,-l, 0,0,1, video::SColor(255,255,255,255), t, t);
// create left side
Material[1] = mat;
Material[1].Texture1 = rt[2];
Vertices[4] = video::S3DVertex( l,-l,-l, -1,0,0, video::SColor(255,255,255,255), t, o);
Vertices[5] = video::S3DVertex( l,-l, l, -1,0,0, video::SColor(255,255,255,255), o, o);
Vertices[6] = video::S3DVertex( l, l, l, -1,0,0, video::SColor(255,255,255,255), o, t);
Vertices[7] = video::S3DVertex( l, l,-l, -1,0,0, video::SColor(255,255,255,255), t, t);
// create back side
Material[2] = mat;
Material[2].Texture1 = rt[5];
Vertices[8] = video::S3DVertex( l,-l, l, 0,0,-1, video::SColor(255,255,255,255), t, o);
Vertices[9] = video::S3DVertex(-l,-l, l, 0,0,-1, video::SColor(255,255,255,255), o, o);
Vertices[10] = video::S3DVertex(-l, l, l, 0,0,-1, video::SColor(255,255,255,255), o, t);
Vertices[11] = video::S3DVertex( l, l, l, 0,0,-1, video::SColor(255,255,255,255), t, t);
// create right side
Material[3] = mat;
Material[3].Texture1 = rt[3];
Vertices[12] = video::S3DVertex(-l,-l, l, 1,0,0, video::SColor(255,255,255,255), t, o);
Vertices[13] = video::S3DVertex(-l,-l,-l, 1,0,0, video::SColor(255,255,255,255), o, o);
Vertices[14] = video::S3DVertex(-l, l,-l, 1,0,0, video::SColor(255,255,255,255), o, t);
Vertices[15] = video::S3DVertex(-l, l, l, 1,0,0, video::SColor(255,255,255,255), t, t);
// create top side
Material[4] = mat;
Material[4].Texture1 = rt[0];
Vertices[16] = video::S3DVertex( l, l, l, 0,-1,0, video::SColor(255,255,255,255), t, t);
Vertices[17] = video::S3DVertex(-l, l, l, 0,-1,0, video::SColor(255,255,255,255), t, o);
Vertices[18] = video::S3DVertex(-l, l,-l, 0,-1,0, video::SColor(255,255,255,255), o, o);
Vertices[19] = video::S3DVertex( l, l,-l, 0,-1,0, video::SColor(255,255,255,255), o, t);
// create bottom side
Material[5] = mat;
Material[5].Texture1 = rt[1];
Vertices[20] = video::S3DVertex(-l,-l, l, 0,1,0, video::SColor(255,255,255,255), o, o);
Vertices[21] = video::S3DVertex( l,-l, l, 0,1,0, video::SColor(255,255,255,255), o, t);
Vertices[22] = video::S3DVertex( l,-l,-l, 0,1,0, video::SColor(255,255,255,255), t, t);
Vertices[23] = video::S3DVertex(-l,-l,-l, 0,1,0, video::SColor(255,255,255,255), t, o);
}
//! destructor
CRTTSkyBoxSceneNode::~CRTTSkyBoxSceneNode()
{
// drop render targets
for (s32 n=0; n<6; ++n)
rt[n]->drop();
// drop sky camera
skyCam->remove();
}
void CRTTSkyBoxSceneNode::renderToSkyBox(core::vector3df pos, video::SColor col, bool self)
{
ICameraSceneNode *lastcam = SceneManager->getActiveCamera();
SceneManager->setActiveCamera(skyCam);
bool vis; // is visible
if (!self)
{
vis = isVisible();
setVisible(false);
}
skyCam->setPosition(pos);
// render up
SceneManager->getVideoDriver()->setRenderTarget(rt[0], true, true, col);
skyCam->setTarget(pos + core::vector3df(0,10,0));
skyCam->updateAbsolutePosition();
SceneManager->drawAll();
// render down
SceneManager->getVideoDriver()->setRenderTarget(rt[1], true, true, col);
skyCam->setTarget(pos + core::vector3df(0,-10,0));
skyCam->updateAbsolutePosition();
SceneManager->drawAll();
// render left
SceneManager->getVideoDriver()->setRenderTarget(rt[2], true, true, col);
skyCam->setTarget(pos + core::vector3df(10,0,0));
skyCam->updateAbsolutePosition();
SceneManager->drawAll();
// render right
SceneManager->getVideoDriver()->setRenderTarget(rt[3], true, true, col);
skyCam->setTarget(pos + core::vector3df(-10,0,0));
skyCam->updateAbsolutePosition();
SceneManager->drawAll();
// render front
SceneManager->getVideoDriver()->setRenderTarget(rt[4], true, true, col);
skyCam->setTarget(pos + core::vector3df(0,0,-10));
skyCam->updateAbsolutePosition();
SceneManager->drawAll();
// render back
SceneManager->getVideoDriver()->setRenderTarget(rt[5], true, true, col);
skyCam->setTarget(pos + core::vector3df(0,0,10));
skyCam->updateAbsolutePosition();
SceneManager->drawAll();
if (!self) setVisible(vis);
SceneManager->getVideoDriver()->setRenderTarget(0);
SceneManager->setActiveCamera(lastcam);
}
//! renders the node.
void CRTTSkyBoxSceneNode::render()
{
video::IVideoDriver* driver = SceneManager->getVideoDriver();
scene::ICameraSceneNode* camera = SceneManager->getActiveCamera();
if (!camera || !driver)
return;
core::matrix4 mat;
mat.setTranslation(camera->getAbsolutePosition());
driver->setTransform(video::ETS_WORLD, mat);
for (s32 i=0; i<6; ++i)
{
driver->setMaterial(Material[i]);
driver->drawIndexedTriangleList(&Vertices[i*4], 4, Indices, 2);
}
}
//! returns the axis aligned bounding box of this node
const core::aabbox3d<f32>& CRTTSkyBoxSceneNode::getBoundingBox() const
{
return Box;
}
void CRTTSkyBoxSceneNode::OnPreRender()
{
if (IsVisible)
SceneManager->registerNodeForRendering(this, ESNRP_SKY_BOX);
ISceneNode::OnPreRender();
}
//! returns the material based on the zero based index i. To get the amount
//! of materials used by this scene node, use getMaterialCount().
//! This function is needed for inserting the node into the scene hirachy on a
//! optimal position for minimizing renderstate changes, but can also be used
//! to directly modify the material of a scene node.
video::SMaterial& CRTTSkyBoxSceneNode::getMaterial(s32 i)
{
return Material[i];
}
//! returns amount of materials used by this scene node.
s32 CRTTSkyBoxSceneNode::getMaterialCount()
{
return 6;
}
} // end namespace scene
} // end namespace irr
Code: Select all
// make a 512x512 texture skybox
scene::CRTTSkyBoxSceneNode *sky = new
CRTTSkyBoxSceneNode(core::dimension2d<s32>(512,512), smgr->getRootSceneNode(),smgr,0);
// make your main scene invisible
gameSceneRoot->setVisible(false);
// render sky, sun, clouds, whatever with default blue bg
backgroundsky->setVisible(true);
sky->renderToSkyBox(core::vector3df(0,0,0));
backgroundsky->setVisible(false);
// render distant landscape with sky
distantTerrainRoot->setVisible(true);
sky->renderToSkyBox(zoneposition, video::SColor(0,0,0,0), true);
distantTerrainRoot->setVisible(false);
// carry on with game
gameSceneRoot->setVisible(true);