Yeah baked terrains can't be used for First person camera.
Code: Select all
#include <irrlicht.h>
#include <cassert>
using namespace irr;
//simple node for drawing a quad. Based on the irrlicth example of a custom scene node
class CQuadNode : public virtual scene::ISceneNode
{
core::aabbox3d<f32> Box;
video::S3DVertex Vertices[4];
video::SMaterial Material;
bool Textured;
public:
CQuadNode(scene::ISceneNode* parent, scene::ISceneManager* mgr, s32 id=-1)
: scene::ISceneNode(parent, mgr, id)
{
Material.Wireframe = false;
Material.Lighting = false;
//important!
Material.TextureLayer[0].TextureWrapU=video::ETC_CLAMP_TO_EDGE;
Material.TextureLayer[0].TextureWrapV=video::ETC_CLAMP_TO_EDGE;
Textured = false;
Vertices[0] = video::S3DVertex(0,0,0,
0,1,0,
video::SColor(255,255,255,255), 0, 0);
Vertices[1] = video::S3DVertex(16,0,0,
0,1,0,
video::SColor(255,255,255,255), 1, 0);
Vertices[2] = video::S3DVertex(16,0,16,
0,1,0,
video::SColor(255,255,255,255), 1, 1);
Vertices[3] = video::S3DVertex(0,0,16,
0,1,0,
video::SColor(255,255,255,255), 0, 1);
Box.reset(Vertices[0].Pos);
for (s32 i=1; i<4; ++i)
Box.addInternalPoint(Vertices[i].Pos);
}
~CQuadNode()
{
if(Material.getTexture(0)!=0)
Material.getTexture(0)->drop();
}
void setRenderSurface(irr::video::ITexture * rt)
{
assert(rt!=0);
assert( rt->isRenderTarget()); //we early catch user errors if they forget to provide a render target.
Material.setTexture(0,rt);
rt->grab();
Textured = true;
}
virtual void OnRegisterSceneNode()
{
if (IsVisible)
SceneManager->registerNodeForRendering(this);
ISceneNode::OnRegisterSceneNode();
}
virtual void render()
{
u16 indices[] = { 2,1,0, 3,2,0 };
video::IVideoDriver* driver = SceneManager->getVideoDriver();
driver->setMaterial(Material);
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
driver->drawVertexPrimitiveList(&Vertices[0], 4, &indices[0], 2, video::EVT_STANDARD, scene::EPT_TRIANGLES, video::EIT_16BIT);
}
virtual const core::aabbox3d<f32>& getBoundingBox() const
{
return Box;
}
virtual u32 getMaterialCount() const
{
return 1;
}
virtual video::SMaterial& getMaterial(u32 i)
{
return Material;
}
};
//This demo will show a possible usage of RTT textures.
//We will draw few items on a texture once and then we will use the texture forever.
//This tecnique can be used for updating terrain tiles in a way to achieve high high quality and
//detail thus with high performance. Artist will do great things with this.
video::ITexture * splat1 = 0;
video::ITexture * splat2 = 0;
video::ITexture * splat3 = 0;
void draw1(irr::video::IVideoDriver* driver);
void draw2(irr::video::IVideoDriver* driver);
int main()
{
IrrlichtDevice *device = createDevice(video::EDT_OPENGL,
core::dimension2d<u32>(1000, 600), 32, false);
assert(device!=0);
device->setWindowCaption(L"Example of splatting.");
video::IVideoDriver* driver = device->getVideoDriver();
scene::ISceneManager* smgr = device->getSceneManager();
///this example will work only with Render to texture.
assert( driver->queryFeature(video::EVDF_RENDER_TO_TARGET) );
scene::ICameraSceneNode* camera =
smgr->addCameraSceneNodeFPS(0,15.0f,0.5f);
camera->setPosition(core::vector3df(130,70,11));
camera->setTarget(core::vector3df(0,0,0));
camera->setFarValue(1000.0f);
camera->setNearValue(10.f);
// disable mouse cursor
device->getCursorControl()->setVisible(false);
video::ITexture* rt1 = driver->addRenderTargetTexture(core::dimension2d<u32>(512,512), "RTT1", video::ECF_R8G8B8);
video::ITexture* rt2 = driver->addRenderTargetTexture(core::dimension2d<u32>(512,512), "RTT2", video::ECF_R8G8B8);
assert(rt1!=0);
assert(rt2!=0);
splat1 = driver->getTexture("media/stones2.png"); //128x128 image
splat2 = driver->getTexture("media/wall.png"); //512x512 image
splat3 = driver->getTexture("media/water.png"); //256x256 image
assert(splat1!=0);
assert(splat2!=0);
assert(splat3!=0);
CQuadNode *tile1 =
new CQuadNode(smgr->getRootSceneNode(), smgr);
CQuadNode *tile2 =
new CQuadNode(smgr->getRootSceneNode(), smgr);
tile1->setPosition(core::vector3df(0,0,0));
tile2->setPosition(core::vector3df(16,0,0)); //place the 2nd tile next to the 1st
tile1->setScale(core::vector3df(1.0005,1,1.0005));
tile2->setScale(core::vector3df(1.0005,1,1.0005));
//is possible that some videocard will show seams on edges (very common bug)
//so it is better to scale the node in X,Z dimensions by a very small factor (1/1000 or similiar)
tile1->setRenderSurface(rt1);
tile2->setRenderSurface(rt2);
tile1->drop();
tile2->drop();
bool Render=true;
while(device->run())
{
driver->beginScene(true, true, video::SColor(0,100,100,100));
if(Render)
{
driver->setRenderTarget(rt1, true, false, video::SColor(0,0,0,0));
draw1(driver);
driver->setRenderTarget(rt2, true, false, video::SColor(0,0,0,0));
draw2(driver);
Render = false; //we need just to draw once for this demo.
//you can still draw more often if you want to render to terrain tiles for example
// but usually there's abosolutely no need for render to tetxures each frame.
//anyway unless you are going to render 1000 objects to each texture you can
//do RTT at each frame. (but why upating every frame if not really needed? :D)
driver->setRenderTarget(0,true,true);
}
smgr->drawAll();
driver->endScene();
}
device->drop();
return 0;
}
//2 drawing lists. There is only 1 list needed for each RT
void draw1(irr::video::IVideoDriver* driver)
{
driver->draw2DImage(splat1,core::position2di(110,50),core::recti(0,0,128,128),0,video::SColor(255,255,255,255),true);
driver->draw2DImage(splat2,core::position2di(256,0),core::recti(0,0,512,512),0,video::SColor(255,255,255,255),true);
}
void draw2(irr::video::IVideoDriver* driver)
{
driver->draw2DImage(splat2,core::position2di(-256,0),core::recti(0,0,512,512),0,video::SColor(255,255,255,255),true);
driver->draw2DImage(splat3,core::position2di(30,30),core::recti(0,0,256,256),0,video::SColor(255,255,255,255),true);
}
and a screen shot ( I modified a bit 3 of the irrlicht's media files with GIMP for adding an alpha layer and some transparency, you can see the wall through the water)
in this example there are 2 tiles of 512x512 size (can be bigger as well) and 3 textures splatted. 1 Texture is splatted twice.
well I worked a lot also with masks and texture atlas . This depends on if you implement new cameras or not
. You can use a mixed approach so that far textures uses a mask while near textures uses few baked terrains with a shader for smooth transition (a bit complex XD but viable). At you the choice. The terrain system you are using now seems enough for baked terrains. You need just to wrap 1 texture across 1 or more tiles (if the tile are small then wrap UV to group of 4 tiles instead of 1 tile).
Textures bigger than 2048x2048 are not needed since most monitors don't have more than 1366 in width.