Detail texture techniques

Started by
15 comments, last by MickePicke 19 years ago
Buttza:

Hi there, I looked at your screenshot with interest. However I find your method a bit hihg-powered for the results it gives. It's pretty but when you take away the (very nice) water it's very similar to what I have, using two textures only in a single pass on a TNT2 with no shaders. Maybe that's just because you aren't fully utilising the capabilities of your engine with the map shown in that shot - it's basically just sand and grass. I didn't follow all of your description since I don't know shaders - how many different groundtypes can you use? I mean how many different detail textures for grass, sand etc are supported in a level? Did you say 4/8, and does just rely on the GPU having 4/8 texture units? When you mention multiple passes is that so you can handle more detail textures?
Finally, you have 'layer 1 mask', 'layer 2 mask' etc which tells how much of each groundtype to use, are these masks stetched over the whole map or tiles of some kind?

Feel free to PM me if you fancy a chat about these things and don't want to derail the thread...
Advertisement
Thanks alot Buttza, you've been very helpful and the images realy made the difference in understanding the DT layer mask creation algorithm.

Btw, what water technique is it that you're using on the first screenshot you posted? Just interrested because it resembles the Far cry water alot.
Well my algorithm may be a little "lame" because it doesnt take the overall intensity of the layers into account, but all in all, i have only found 1 small error in the whole farcry demo map. This is how it works:

// This shows the assignment of different DetailLayers to the color registerint iLayers[4] = {-1,-1,-1,-1};// Chunksize=33x33 vertices for me ( same as farcry )unsigned char* pSpace=new unsigned char[m_iChunkSize*m_iChunkSize];// Initialize pSpace to 255 here! ( i took some part of the code out )	int v=0;// make sure youve got the right traversal direction here!for (int m=m_DetailLayers.size()-1;m>=0;m--){    // this variable determines to which color the next found layer is assigned	int iWriteToColor=-1;	// Check if the layer is already assigned to this chunk, if so, get the index	for (int lay=0;lay<iLayerCount;lay++)	{		if (!stricmp(m_DetailLayers[iLayers[lay]]->chDetailTexture,m_DetailLayers[m]->chDetailTexture))		{			iWriteToColor=lay;			break;		}	}		v=0;	tDetailLayer* detlay=m_DetailLayers[m];	for (int r=0;r<m_iChunkSize;r++)	{		for (int c=0;c<m_iChunkSize;c++)		{			// these are the actual xy positions on the alpha map of the layer			int x=i+c;			int y=j+r;			unsigned char intensity=GetIntensity(detlay->pMask,x,y);			if (intensity==0) continue;						unsigned char& iSpace=pSpace[r*m_iChunkSize+c];			// this means we have used up our space... since the total intensity ( r+g+b+a should be =255 )			if (iSpace<=0) continue;			// If the layer is not assigned to the chunk yet, check if we are below the layer limit (4)			// and exclude very low values			if (iWriteToColor==-1)			{				if (iLayerCount<4)				{					// this makes sure that low intensities at a point dont insert a whole layer into the current chunk					if (intensity<10) continue;					// now we've found the color where we want to write to					iWriteToColor=iLayerCount;					iLayers[iLayerCount++]=m;				}				// This means exactly that there are not enough layers (4 max ) to hold the current layer as well. This may result in visual problems				//else					//CLog::Inst()->Error("CTerrain::LoadHeightmap Layer overflow!");			}			if (iWriteToColor!=-1)			{				// make sure the intensity is not bigger than the space we have ( 255 max because r+g+b+a=255 )				if (iSpace-intensity<0) intensity=iSpace;				// this actually stores the intensity in the color of the current vertex.				pColors[((r*m_iChunkSize+c)*4)+iWriteToColor]+=intensity;				iSpace-=intensity;			}		}	}}
Quote:
However I find your method a bit hihg-powered for the results it gives. It's pretty but when you take away the (very nice) water it's very similar to what I have, using two textures only in a single pass on a TNT2 with no shaders. Maybe that's just because you aren't fully utilising the capabilities of your engine with the map shown in that shot - it's basically just sand and grass.


By using one single base terrain texture you get variety in the terrain that you just don’t get with multiple textures blended using alpha maps. It also allows you to apply static lighting and shadows, eg. from the sun, on the base texture instead of in a separate lightmap.

This allows you to render the terrain in one pass using one texture. Of course unless the base texture is of ultra high resolution it will appear blurry. This is why we use detail textures to 'simulate' detail up close. Take a look at the game FarCry for a demonstration of this technique in action because as you pointed out my screenshot doesn't show it off fully.

Quote:
I didn't follow all of your description since I don't know shaders - how many different groundtypes can you use? I mean how many different detail textures for grass, sand etc are supported in a level? Did you say 4/8, and does just rely on the GPU having 4/8 texture units? When you mention multiple passes is that so you can handle more detail textures?
Finally, you have 'layer 1 mask', 'layer 2 mask' etc which tells how much of each groundtype to use, are these masks stetched over the whole map or tiles of some kind?


Unlimited number of layers. Fixed number of surfaces. Read my descriptions above on the differences between the two. FarCry limits the number of surfaces to 7. In my engine I limit it to 8, though theoretically it could be unlimited.

Quote:
Thanks alot Buttza, you've been very helpful and the images realy made the difference in understanding the DT layer mask creation algorithm.

Btw, what water technique is it that you're using on the first screenshot you posted? Just interrested because it resembles the Far cry water alot.


No problem Cybrosys. The water looks similar because it’s using the same technique as FarCry. Read up on the many threads here on gamedev regarding water or read Yann L’s article on Realistic Natural Effect Rendering: Water I. My water is based on that article.

Quote:Well my algorithm may be a little "lame" because it doesnt take the overall intensity of the layers into account, but all in all, i have only found 1 small error in the whole farcry demo map.


Nice. As I thought you’re checking each surface mask for an intensity > 10. I'll remember that if I need to optimize. Thanks.
Oh no sorry my definition of passes is wrong. I meant setting two texture units, then doing one pass for each ground type. So I draw the base colour map first as you do. Then blend the detail maps in, but without needing blend textures or shaders.

Hello!
All your explanations are usefull, this technique produces really nice screen shot!
I'm working on such technic, and i constantly search the way far cry works.

And i've understood (thanks) the difference between layers and surfaces.
In fact if i'm right the only final difference between the two will be the base texture, which is alpha blended, who produces more or less noise, and more or less colour variation.
Simple.
Thanks for your explanations because i didn't understand how they can fit so much alpha textures in memory (i try to fit in 64 Mb of graphic card memory). With 7 or 8 surfaces, it's much more simple.
Currently i use 1024*1024 alpha maps, but it lacks precision from far (it's beautiful when detail textured). So i'll change these maps' resolution.


I really think far cry doesn't use a per-vertex alpha variation, because if you look attentively in sand box, there are roads, and the roads have on their center a little bit of grass (and you can add/substract grass manually). The roads aren't decals, so i you alpha blend per vertex you will not have suffisent precision.


I saw recently that far cry uses fog to fade between detail texture to base texture, it's really visible when you disable fog in sand box.

To make transition between the two, i think it's possible they have used vertex
shaders to change alpha per vertex (0 or 1) according to the distance from the camera.
I never done shaders so i could just imagine.

When we approach ground we see that the spheric zone where we are shows detail texture, the limit isn't chunk-based, but vertex-based (see in wireframe with no fog).
Currently i'm rendering the entire chunk with a global-per-chunk-alpha to make the detail texture appearing softly, but when the chunk near it isn't detail textured (bounding box too
far), it's really ugly.
I would need to know the nearest vertex of a chunk from the camera,
but i don't know how to do that for the moment.
When the rest will be nice (lot of work), i'll look for the vertex shaders.

This thread rocks!
Buttza rating++

This topic is closed to new replies.

Advertisement