Texture Creation
description
Creating a grass detail sprite for use on displacements.
keywords
sprite, 2D, grass, detail, displacement, texture, surface, vtf.
For more information on Detail Sprites and the Parameters assosiated with them head over to the VDC: http://developer.valvesoftware.com/wiki/Detail_Props#New_detail_types
What is a Detail Sprite?
A detail sprite is a raster image (2D or "flat") which gets generated on a displacement surface during compilation. Frequently used for grasses and plants.
In this tutorial we will be looking strictly at spawning 2D sprites, not 3D models. However I may update that in later on. Its a very similar process to the 2D sprites we will be making so take a peek at the VDC link at the top to learn more.
Hierarchy of what we will be doing in this tutorial:
Creating the Sprite Texture:
The sprite texture should contain each of the sprites you'd like to use in a particular level, you can only use one sprite texture per individual level. Individual sprites do not get their own texture.
Material Texture (VTF):
When creating a sprite sheet make sure to leave adequate spacing between each one as to avoid one from bleeding into another. While your sheet doesn't have to be as organized as mine it will make your work easier in the long run to know where everything is mapped out. This includes the top right corner of each sprites origin, the sizes of each sprite, in pixels, and their origins. Origins are where the sprite will rotate or spin so that they always be facing toward you. This is done by using X, Y coordinates between 0 - 1. 0.5, 1 would mean half way across the horizontal and on the bottom.
NOTE each cutout does not have to be a power of 2, it can be any size on the sprite sheet you like, mine is just simplified for the tutorial.
I placed my sprites on a 512x512 texture, then I went ahead and made a new layer to map out the locations of each sprite.
When you are happy with the positioning of your sprites save the guide as a separate picture for reference use later on. Now you should remove or hide the guides layer and flatten all the individual sprites onto a single layer if they aren't already (Ctrl + E). Now the sprites are going to need a transparency mask so that I don't just have white squares with plants in the middle. One way of cutting out the solid white background out is by going to "Filter, Colour Range" and by clicking on the whites they should now all be selected, hit your delete key to remove them.
Now while holding ALT click on your Sprites Layer (On the thumbnail specifically) this will select your sprite cutouts and while selected go over to your Channels tab and click on the create layer mask button. You can see my new "Alpha 1" layer is now created with all the sprites in white, or the unmasked part, while all the empty space is in black, or where your texture will be masked/transparent in the game. Save your texture as a VTF, compressed texture with Alpha.
Photoshop VTF pluging can be found here: http://nemesis.thewavelength.net/index.php?c=154#p154
Material Parameters (VMT):
I saved my VTF as examplesprites.vtf in the /materials/whiffen folder. The vmt should reflect where you have it stored under $basetexture. You can create a vmt by making a new txt document, pasting and editing these parameters to your liking and saving it as examplesprites.vmt under *All File Types*
- Code: Select all
UnlitGeneric
{
$baseTexture "whiffen\examplesprites"
$translucent 1
$nocull 1
$vertexcolor 1
$vertexalpha 1
$receiveflashlight 1
$singlepassflashlight 1
}
You've now completed your sprite texture, next step is to tell the engine where these sprites are and how it should handle generating them on surfaces.
Creating the Detail.vbsp:
The original Valve file can be found at the root directory of your game, named detail.vbsp, however when you create yours you can save it to a different location, if you want to save it to your root directory you should name it differently as not to override Valves. I will call mine examplegrasses.vbsp.
D:\Steam\SteamApps\common\left 4 dead 2\left4dead2 is the root directory for the game I'm working on.
You can open a vbsp in any text editor, and we will create one the same way as we did our vmt, by creating a new txt document first and saving it afterwards as examplegrasses.vbsp under allfiles.
Now let me take you though the syntax.
- Code: Select all
detail
{
<Detail type>
{
density <float>
<Group>
{
alpha <normal>
<Prop>
{
<settings>
}
}
}
}
All <detail>.vbsp's will start with detail {.
Detail type is the name you wish to call a specific grouping, you can have as many as you want in your vbsp. For example if you create a detail type named swamp_foliage and set it to use things like cat tails and tall grasses and another one named forest_foliage for small plants and grasses you can choose the appropriate one for your texture by adding it to that textures vmt with "%detailtype swamp_foliage/forest_foliage"
Density defines how densely sprites are placed.
Groups are used to divide the alpha channels of a displacement. Lets say you have a blend texture between concrete and grass. Your concrete texture is the main basetexture or Alpha 0, the grass is basetexture2 or Alpha1. On your concrete texture you don't want any grass sprites to spawn on it so you would define alpha 0 with no props like such;
- Code: Select all
Group 1
{
alpha 0
}
Where as alpha 1, the grass texture, will spawn sprites.
- Code: Select all
Group 2
{
alpha 1
Grass Sprites
{
sprite ~
spritesize ~
spriterandomscale ~
amount ~
}
}
Alpha as briefly described above sorts what type of or how many sprites you want on a particular blended surface. It doesn't have to be as black and white as 0 and 1, you can use any value in between like 0.5 if you wanted a particular sprite to be placed half way between one blended surface and another. For instance if you had tall grasses placed on alpha 0 and cattails on alpha 1 a sharp transition between the two might not be the effect you were looking for. Adding an alpha group at 0.5 with medium sized grass sprites and a few cattails blended in would help make the transition between the two blended textures less sharp.
Prop Is just a place holder for defining which sprites you want to use in a particular group. I could just name sprites Prop1, Prop2, etc. Or I could name them specifically based on the sprite they represent. If I decided to use a cattail sprite I could call this cattail, so when I go back into my detail.vbsp later to change things I know exactly what is what.
Settings this is where you define where the sprite is on your sprite texture, how big it is in the game, how much is sways back and fourth, what shape it is, randomly generated sizes, where its origin is and every other aspect of this particular sprite.
There are way to many settings for me to go though in this tutorial but I will help you get started by choosing the correct sprite, its size and the random scale. Please refer to the VDC at the top of this tut for more information, its already all there for you and wouldn't make much sense for me to write everything all over when they have done an excellent job already.
Coming back to this image I am going to set up the first sprite for you. Every sprite will require a minimum of these first 2 commands.
sprite "0 0 128 256 512"
spritesize "0.5 1 16 32"
spriterandomscale .15
sprite X, Y, W, H, VTF width
The subregion of the map's detail material to use for this prop.
* X/Y are the top-left position
* W/H are the dimensions of the prop in texels
* VTF width is the X-axis resolution of the whole detail texture.
spritesize <normal|U, V> <float|W, H>
The origin (U/V) and size in units (W/H) of the sprite when it is in the world.
spriterandomscale <normal>
The sprite's size will vary from 100% by this degree. A value of 1 means that the sprite could be generated at anything between 0% and 200% of its normal size.
This is what my completed detail.vbsp looks like.
- Code: Select all
detail
{
example_grasses //Detail Type, Name this related to the sprites you plan to use. Swamp_foliage, Dry_Grasses, etc...
{
density 2000 // How densely sprites are placed
Group1 // First grouping in this detail type
{
alpha 0 // Applies to my Basetexture
}
Group2 // Second grouping in this detail type
{
alpha 1 // Applies to my Basetexture2
Cattail // Name for my first sprite
{
sprite "0 0 128 256 512" // The sprites location on the texture
spritesize "0.5 1 16 32" // The Origin and how big it appears in game
spriterandomscale .15 // Random sizing multiplier
spriteorentation 2 // How it looks in game ( Always faces you, Always stationary, etc...)
amount .1 // Amount of these sprites compared to the others in this Group. 0.1 = 10% of the sprites in this grouping will be this sprite. All the sprites in a group should equal 1, any less you won't be using the full density you set above, any more you will have a higher density.
sway .5 // How far this sprite sways back and fourth. "Simulated wind"
maxangle 95 // Max degrees the sprite will turn in order to face you.
}
Wheatthing
{
sprite "128 0 128 256 512"
spritesize "0.5 1 16 32"
spriterandomscale .15
spriteorentation 2
amount .3
sway .5
maxangle 95
}
TangledMotherfucker
{
sprite "256 0 256 256 512"
spritesize "0.5 0.8 32 32"
spriterandomscale .15
spriteorentation 2
amount .1
sway .3
maxangle 95
}
Grass
{
sprite "0 256 512 256 512"
spritesize "0.5 1 128 64"
spriterandomscale .15
spriteorentation 2
amount .5
sway .3
maxangle 95
}
}
}
}
Creating the Displacement Surface:
Hopefully you already have a displacement texture created, so how do we apply our above sprites to our displacement? We do it though the %detailtype. Looking back at my vbsp you can see I named this specific detail group "example_grasses" so just sub that into your displacements vmt and your all set!
- Code: Select all
LightmappedGeneric
{
$basetexture whiffen\dirta
$basetexture2 whiffen\dirtb
$surfaceprop gravel
$surfaceprop2 gravel
%detailtype example_grasses //LOOK HERE
}
Setting up Hammer:
Last thing to do is setup hammer to use your custom sprites texture and detail.vbsp by going to: map, map properties.
All done! Your sprites wont show up in hammer but it should work after compiling.
FINAL RESULT: Hopefully yours will be better than mine, I didn't spend to much time on mine