Block Land 4

From DaveWiki

Jump to: navigation, search

Last Time we got our mesh chunking working pretty good and now we'll take a little bit of time to make our world look better.

Contents

Textures

So far we've just been coloring our blocks with a solid color texture and now we'll move to actual image textures. The mesh chunking code already sets the UV texture coordinates for each triangle so it should be a simple matter of making the material. To keep it looking like MineCraft we'll use a small 16x16, 32 bit image for the texture:

Grass 16x16 Texture

Certainly not the best grass texture ever but quite usable for now. If you're using the default project paths then you'll need to stick this in your Ogre\media\materials\textures directory. Creating a material to use this image programmatically is not too hard:

void TestBlockLandApplication::createSolidTexture (const TCHAR* pName)
{
	Ogre::MaterialPtr mat = Ogre::MaterialManager::getSingleton().create("BoxColor", "General", true );
	Ogre::Technique* tech = mat->getTechnique(0);
	Ogre::Pass* pass = tech->getPass(0);
	Ogre::TextureUnitState* tex = pass->createTextureUnitState();
	tex->setColourOperationEx(Ogre::LBX_MODULATE, Ogre::LBS_MANUAL, Ogre::LBS_CURRENT, Ogre::ColourValue(0, 0.5, 0));
}
 
void TestBlockLandApplication::createTexture (const TCHAR* pName, const TCHAR* pImageFilename)
{
	Ogre::MaterialPtr mat = Ogre::MaterialManager::getSingleton().create("BoxColor", "General", true );
	Ogre::Technique* tech = mat->getTechnique(0);
	Ogre::Pass* pass = tech->getPass(0);
	Ogre::TextureUnitState* tex = pass->createTextureUnitState();
 
	tex->setTextureName(pImageFilename);
	tex->setNumMipmaps(4);
	tex->setTextureAnisotropy(1);
	tex->setTextureFiltering(Ogre::FO_POINT, Ogre::FO_POINT, Ogre::FO_POINT);
}

The first method just creates a simple solid greenish color texture like we used before. The second method uses an image file to created a textured material that will display like the MineCraft blocks. If you omit some of the settings like anisotropy and filtering then your texture ends up blurry. Changing the code to use this material and rendering a small test world results in:

16 Block Spherical World With Simple Grass Texture

Sky Dome and Fog

A sky dome (or box, or plane) is a static object centered on the player that displays, as you might have guessed, the sky. Fog is just the technique to make distant objects fade out into a set background color. Fortunately, Ogre makes it real easy to add these features to our scene:

        mSceneMgr->setSkyDome(true, "Examples/CloudySky", 2, 8, 100);
	mSceneMgr->setFog(Ogre::FOG_LINEAR, Ogre::ColourValue(0.8,0.8,1), 0.05, 0.0, 200);
 
	mCamera->setFarClipDistance(256);
	mCamera->setNearClipDistance(0.01);

I had to play with the sky and fog settings a bit to make them look good for our situation in addition to modifying the default Examples/CloudySky material in the Ogre\media\materials\scripts\Exmaples.material file:

material Examples/CloudySky
{
	technique
	{
		pass
		{
			lighting off
			depth_write off
			depth_check off
			fog_override true
 
			texture_unit
			{
				texture clouds.jpg
				scroll_anim 0.05 0
			}
		}
	}
}

I slowed down the scrolling animation a bit and added options to turn off the depth and fog checks (otherwise the sky box won't work well with the fog settings). Back to rendering our large 256 block sphere with these additions gets us:

256 Block Spherical World With Sky Dome and Fog

I still don't expect any graphical awards for this but with just a few simple changes it is beginning to look more like a playable world.

Better Landscapes

At this point I'm getting tired of seeing random or spherical block worlds. As nice as they are they are ultimately not anything what we want our world to look like. I'll be using some procedural landscape generation code I worked on in the past that uses the Perlin noise from the libnoise library . See the Erosion article series for more details. For now I won't be using any advanced feature of my landscape generation so it will be identical to grabbing the height map directly from the libnoise noiseutils code directly. The short story is that a height map is just a 2D gray scale image indicating the height of the terrain (lighter is typically higher land), for example:

Basic Height Map

For now our block world is going to be solid beneath the height generated from our height map making our landscape generation code very simple:

class TestBlockLandApplication : public BaseApplication
{
...
        infland::CLandscape m_Landscape;
};
 
 
void TestBlockLandApplication::initWorldBlocksLand()
{
	m_Landscape.SetSize(WORLD_SIZE, WORLD_SIZE);
	m_Landscape.CreateAltitude();
 
	infland::CMap& Map = m_Landscape.GetAltitudeMap();
 
	for (int z = 0; z < WORLD_SIZE; ++z)
	{
		for (int x = 0; x < WORLD_SIZE; ++x)
		{
			float Height = Map.GetValue(x, z) * WORLD_SIZE/4 + WORLD_SIZE/2;
 
			for (int y = 0; y < Height; ++y)
			{
				GetBlock(x, y, z) = 1;
			}
 
		}
	}
 
}

Note that the * WORLD_SIZE/4 + WORLD_SIZE/2 factor is converting the raw height values which go from -1.0 to +1.0 into our world coordinates. This scaling can be played with to adjust how steep and tall our hills and mountains will be. The glorious result of all this is some decent looking world scapes in a 256 block sized world with 64 block chunks:

Looking Down from the Mountain

Looking Up Towards the Mountains

Some notes on our progress so far:

  • It may be no Oblivion but it looks good despite only using a dead simple world generation and display method and only one block type.
  • Performance is very good on our mid-end system and we haven't really tried to optimize anything beyond chunking. FPS is above 100 everywhere and RAM usage is around the 400MB mark.

Next Time

Next Time we'll look at an obvious optimization and discuss how it and the world/chunk sizes effect how we handle things.

Personal tools