Grass

Published April 26, 2010
Advertisement
Its 2 am so I will just post a screenshot for now.I will describe how I did the grass effect later.



Good night journal ! :)

Ok here is how the grass is done.

First of the grass is a 3d model created in a modelling program.It looks like this :



And this is the texture map on it(it is ugly but it can be improved by an artist) :




The only thing left to do is to place these models around the player.It is possible to do it by hand in the world editor but it would take a huge amount of time considering the size of the map so I made a method that automatically places these models around the player depending on the blend maps of the terrain.The terrain can have 8 different textures which are blended with 2 alpha maps,the red component of the first alpha map tells which areas should be grass,so the grass model is only placed on the terrain if the red component of the alpha map beneath is greater than 150.The models are also rotated to align them with the terrain normal under them.Here is the method that does this(not cleaned and optimized yet :))

void DARenderer::drawGrass(float elapsedTime){	Vector3 playerPos = m_World->getPlayerPosition();			boost::shared_ptr model = m_ModelMngr->getModel("grass.X");	STE::EffectPtr effect = m_Effects["model.fx"];	D3DXMATRIX worldMatrix,rotationMatrix;	D3DXMatrixIdentity(&worldMatrix);	float x,y=0,z;	setTransform(D3DTS_WORLD,&m_Identity);	boost::shared_ptr<const GeoMipmapTerrain> terrain = m_World->getMap()->getTerrain();	const GeoMipmapTerrain::VertexBlendData* data = terrain->getAlphaMapData1();		int indexX =  (playerPos.x)*1024 / (terrain->getScale()*(terrain->getSize()-1));	int indexZ = -(playerPos.z)*1024 / (terrain->getScale()*(terrain->getSize()-1));	int imageX = indexX;	int imageZ = indexZ;	effect->SetBool("g_EntitySkinned",FALSE);					Vector3 groundNormal;	for(int i=-10; i<10; ++i)		for(int k=-10; k<10; ++k)		{			imageX = indexX + k;			imageZ = indexZ + i;						if(data[imageX + imageZ * 1024].r >= 150)			{				x = (imageX/1024.0f)*terrain->getScale() * (terrain->getSize()-1);				z = -(imageZ/1024.0f)*terrain->getScale() * (terrain->getSize()-1);				Vector3 pos(x+0.1f,y,z+0.1f+sin((float)(imageX))*2);								if(terrain->getHeight(pos,y,&groundNormal))				{					Vector3 rotationAxis;					Vector3 up(0.0f,1.0f,0.0f);					STMath::Cross(rotationAxis,up,groundNormal);					float angle=STMath::AngleBetweenVectors(up,groundNormal);					D3DXMatrixRotationAxis(&rotationMatrix,(D3DXVECTOR3*)&rotationAxis,angle);										D3DXMatrixTranslation(&worldMatrix,pos.x , y, pos.z);										worldMatrix = rotationMatrix*worldMatrix;					this->drawModel(model.get(),effect,"Grass",worldMatrix);				}			}		}}


This screenshot shows how the models are not placed on the dirt path.It is all automatic if you go in the world editor and paint dirt or any other material it removes the grass models around the player.



Some imrovements can be made,one of them is frustum culling right now almost half of the grass models are not visible since they fall behind the camera.Another improvement will be the grass texture.Multiple models can be used and swapped to give a more random feel and so on.

Edit :
Added frustum culling and increased the visibility range of the grass.Also added simple animation to the grass inside the vertex shader.
I have uploaded the test app to my site, here is the link :
Download

Let me know how fast(or slow :)) it runs.
Previous Entry Missing texture
Next Entry Vertical
0 likes 3 comments

Comments

Deyja
Using pre-multiplied alpha will let you get rid of that black border around your grass.
May 01, 2010 06:40 AM
Black Knight
I tried using pre-multiplied alpha but any kinda of mipmapping causes lots of white borders around the grass if I set :

sampler g_GrassTextureSampler = sampler_state
{
Texture = <ModelTexture>;
MinFilter = None;
MagFilter = None;
MipFilter = None;
};

Then things look better but this time it kills the eyes as there is no filtering.
May 01, 2010 01:18 PM
Deyja
It's possible that your grass texture has solid white in the transparent parts, and creating the mipmaps causes that to bleed in. That shouldn't be a problem unless you're multiplying by alpha in the shader. If this is what's causing it, you could switch to a texture format that preserves the color of transparent pixels, or you could multiply the alpha in when the texture is loaded, before mipmaps are created.
May 01, 2010 03:10 PM
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!
Advertisement

Latest Entries

Advertisement