Creating a Material: Difference between revisions

From Valve Developer Community
Jump to navigation Jump to search
(→‎Adding a normal map (aka bump map): added normal map step details)
(→‎Syntax: hyperlinks good)
 
(87 intermediate revisions by 39 users not shown)
Line 1: Line 1:
[[category:material system]][[category:tutorials]]
{{LanguageBar}}
{{hl2}} This tutorial is a step-by-step process you can go through to create a great-looking material.  Currently, it doesn't cover refractive materials, animations, water, terrain, or skyboxes.


==Making the textures==
{{toc-right}}
This tutorial is a step-by-step guide to creating a brand new [[material]], including the creation of the material's [[texture]].


'''1.''' Choose your material dimensions, and work on your texture at twice that. Dimensions must be in powers of two but do not have to be square. For textures that appear on large surfaces a good scale is 512 pixels for 10 feet (3.0 meters) in the game. For models which have more detail, try to match the resolution of models you’ve seen in HL2. If your resolution is too high, it will actually look worse because of mipmapping. When it’s done, scale it down to the appropriate dimensions and save it as an uncompressed [[TGA]] file in this folder:
== Creating a Texture ==
Any image file can be used as a texture, so long as both of its dimensions (height and width) are a power of two (1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096). To decide which to use, examine existing textures that fill the same role as yours. Higher resolutions lower performance but make an image sharper when viewed up close.


<code>C:\Program Files\Valve\Steam\SteamApps\''Username''\sourcesdk_content\''gameshortname''\materialsrc</code>
Different classes of object have different standard resolutions (e.g. character models' are very high). Check Valve's choices in {{code|hl2_textures_dir.vpk}} (from {{hl2|1}}) with [[GCFScape]] or [[VPKEdit]] if you are ever confused.


'''2.''' Convert the TGA to [[VTF]] by dragging it onto vtex.exe. The VTF will be in this folder:
{{note|Texture source files should be saved in a lossless format like [[Wikipedia:Truevision TGA|TGA]] pre-compile, to prevent unnecessary loss in quality. For textures without an alpha channel, PNG is also acceptable.}}
{{note|The file size limit is 33,554,432 bytes (32 MB). Compiling a .vtf over this amount will cause errors.}}


<code>C:\Program Files\Valve\Steam\SteamApps\''Username''\''gamename''\''gameshortname''\materials</code>
=== Converting the Texture ===


'''3.''' Move your textures to a directory within their current folder (materials). As an example, let's say are creating a texture called <code>brickwall.vtf</code> for Half-Life 2 and want to categorize it under walls. It would go here:
Textures must be converted to the [[Valve Texture Format]] before Source can use them. The tool Valve provides for this is [[Vtex (Source 1)|VTEX]]. It's a [[command line]] tool with quite a few limitations, so the third-party tool {{Vtfedit|4}} (or {{Vtfeditrld|4}}) is preferable: it provides a graphical user interface, allows you to change a texture's properties without re-compiling it from scratch, accepts a wide range of image formats, and doesn't require the creation of script files for every texture. There are a handful of situations where you'll need to fall back on VTEX… but only a handful. Also, if you have textures that use transparency, it is recommended that you save them in TIFF format before importing to VTFedit as PNG transparency tends to have problems.


<code>C:\Program Files\Valve\Steam\SteamApps\''Username''\half-life 2\hl2\materials\walls\brickwall.vtf</code>
(There are VTF plug-ins that let you save to the format directly from [[Photoshop_VTF_Plugin|Photoshop]], [http://code.google.com/p/gimp-vtf/ GIMP], and [http://nemesis.thewavelength.net/index.php?p=50 Paint.NET], but this tutorial will not cover them as not everyone uses those tools.)


==Creating the material file==
'''To import your texture with VTFEdit''', use <code>File > Import</code> or press {{key|Ctrl+I}}. Select your image and you will be presented with the import screen:


A [[VMT]] file is necessary for the material to appear in the game and in [[Hammer]]. Use Notepad to create the VMT, and save it in the same directory as your VTF. (To prevent Notepad from adding .txt to your file name, choose All Files in the dropdown box for file type.)
[[File:Vtfedit importoptions.png|center|VTFEdit's import screen]]


This is the content of the VMT:
==== General settings ====


<pre><nowiki>"shader type"
These settings are the most important. There are three:
{
    "$basetexture" "__"
    "$surfaceprop" "__"
}</nowiki></pre>


Replace "shader type" with one of the following:
; Normal format
: The color/compression format should be used if the texture is opaque.
; Alpha format
: The color/compression format should be used if the texture has an alpha channel.
; Texture type
: Importing more than one image determines what they will be used as (animation frames/cubemap faces/depth slices).


;LightmappedGeneric
If you're making a plain and simple world texture you won't need to change any of these. If you're making a texture with fine gradient detail however, you'll need to [[Valve Texture Format#Choosing_an_image_format|choose a non-lossy compression mode]].
:This is the most common and is used for surfaces you want to be lit normally.


;UnlitGeneric
==== Mipmap settings ====
:This is used for surfaces that are always fully lit like a computer screen or lit lightbulb.


;VertexLitGeneric
[[MIP Mapping|Mipmaps]] are low-resolution versions of a texture that swap in when a surface is far away from the camera. They greatly reduce the amount of texture resizing needed, improving both performance and image quality. Mips are required for texture LOD to work.
:This is used for models.


After "$basetexture" fill in the name of your texture along with its path from the materials folder in quotes.
{{tip|Textures that will appear in the 3D world should have mipmaps. To conserve memory, textures that will only be used in a 2D interface should not.}}


After "$surfaceprop" fill in the surface type in quotes. (This affects the sound of impacts and look of bullet holes.) Choose one of these surfaces: metal, paper, wood, concrete, glass, brick, tile.  For more choices, see [[Material properties]].
The following images demonstrate the various mipmap filters available in VTFEdit:


Here’s what the VMT for the example brick wall texture would look like:
<gallery perrow=5 widths=150 heights=180>
File:Vtf sharpen filters.jpg|Sharpen filters
File:Vtf mipmap filters1.jpg|Mip filters #1
File:Vtf mipmap filters2.jpg|Mip filters #2
File:Vtf mipmap filters3.jpg|Mip filters #3
File:Vtf mipmap filters4.jpg|Mip filters #4
</gallery>


<pre><nowiki>"LightmappedGeneric"
==== Normal map settings ====
{
    "$basetexture" "walls/brickwall"
    "$surfaceprop" "brick"
}</nowiki></pre>


==Adding a normal map (aka bump map)==
These (mislabelled{{how}}) settings allow you to automatically generate a [[bump map]] from your input image. You'll want to do this properly with an image editor for the material you ship, but the automated option is there if you want quick results or a base to work from.
[[Image:Beforenormal.jpg|thumb|Texture that the below normal map is based on.]]
[[Image:afternormal.jpg|thumb|Normal map created from above texture.]]
If your texture is supposed to have depth to it, adding a normal map will make the lighting on it far more realistic. (This is perhaps the main reason Doom3, FarCry, and HL2 are able to look so much better than previous games.) The normal map tells the game what direction each pixel would be facing if your texture were in 3D instead of being a flat image. A normal map is kind of useless for really flat surfaces like smooth concrete or metal. But even rough concrete sometimes has enough depth to it to make a normal map worthwhile. This is an old article but explains the concept well: [http://members.shaw.ca/jimht03/normal.html Normal Maps]


'''1.''' First, create the normal map. If you have Photoshop or PaintShop Pro, you can use Nvidia's normal map tools, available [http://developer.nvidia.com/object/photoshop_dds_plugins.html here]. There are also tools for those who use the GIMP [http://nifelheim.dyndns.org/%7ecocidius/normalmap/ here], but we will focus on the Photoshop tools. To use them, open a copy of the texture and apply the Normal Map filter. Fiddle with the settings until you get something that you feel will be bumpy enough for your texture. The greater the range of colors, the greater the range of angles on the surface.  A very flat surface will look that medium blue color all over.  If you want to have more control over it, change the image to grayscale and fiddle with brightness and contrast to make certain details stand out before applying the filter.  Do this step multiple times to get different details to stand out, and then put the images together in layers with the blend mode set to overlay.
=== Configuring and Saving ===


'''2.''' Save your normal map as a [[TGA]] in the same resolution as the original texture. Give it a name that ends in _normal. Then convert it to a VTF the same way as before. The _normal at the end of the name will affect how [[VTEX]] converts it. For the brick wall example, we would name the file <code>brickwall_normal.tga</code>. Place the new VTF in the same place as your original texture.
When you hit OK the input file is converted (there may be quite a lengthy pause for large images) and the output VTF appears. Now all that is left is configuring the texture with the options in the checkbox list on the left-hand side of the screen. See [[Valve Texture Format#Image_flags]] for descriptions of each.


'''3.''' Add this line to the VMT somewhere between the braces:
Finally, save the file somewhere under your game or mod's <code>\materials</code> folder.


<code>"$bumpmap" "__"</code>
==Creating a Material==
Source doesn't access textures directly. Everything goes through a '''[[material]]'''.


and fill in the path and name of your normal map VTF. The VMT for the example brick texture now looks like this:
Materials are script files that can be created in any text editor, but it's recommended that you use {{npp|4}} in conjunction with the community-made [[Notepad++ VDF languages|syntax highlighting rules]]. For your material to be detected, '''you must save it under your game or mod's <code>\materials</code> folder with the extension <tt>.vmt</tt>'''.
<pre><nowiki>"LightmappedGeneric"
{{note|If you are creating materials and textures exclusively for a map for an existing mod, consider using [[BSPZIP]]\{{pbsp|3.1}}\{{pakrat|3.1}}\{{Compilepal|3.1}} to package the material and texture files within the map file itself. This will prevent them from ever becoming lost.}}
{
{{warning|Although your computer will let you save a file name that contains the <tt>%</tt> character, and [[VTF]]s work just fine with the character in the name, Hammer '''cannot''' handle [[VMT]]s whose names contain the <tt>%</tt> character.}}
    "$basetexture" "walls/brickwall"
    "$surfaceprop" "brick"
    "$bumpmap" " walls/brickwall_normal"
}</nowiki></pre>


Also note that multiple materials can use the same normal map file.
===Syntax===
A material file looks like this:


==Adding reflection (shininess) to a material==
<[[shader]]>
{
<parameter> <value>
...
}


You can add a pseudo-3D reflection to your material. It makes normal mapped materials look far more three-dimensional, because the reflection will bend appropriately according to the normal map. These reflections will be based on the nearest [[env_cubemap]] entity.
  LightmappedGeneric
{
$basetexture coast\shingle_01
$surfaceprop gravel
}


'''1.''' Add this line to your VMT somewhere between the braces:<br/>
There are many [[shader]]s to choose from, but most materials will use either {{ent|LightmappedGeneric}} ([[brush]]es) or {{ent|VertexLitGeneric}} ([[model]]s). The third most common shader is {{ent|UnlitGeneric}}, which is used for [[VGUI2|UI]] materials and the occasional [[tool texture]]. A full list of shaders can be found [[:Category:Shaders|here]].
<code>"$envmap" "env_cubemap"</code>


'''2.''' You will probably want to tone your reflection down by adding this line:<br/>
===Parameters===
<code>"$envmaptint" "[1 1 1]"</code>
:''For a list of all documented shader parameters, see [[:Category:List of Shader Parameters]].''


Change the three ones to make your reflection dimmer. The three numbers scale red, green, and blue individually, but usually, you will want to change all three to the same number. The numbers you put in here will be multiplied by the opacity of the reflection.
With a shader chosen, you're onto parameters (also called commands). There are hundreds of options for what to put in a material so this article will only cover the most common, which are accepted by more or less all shaders. They are:
*{{ent|$basetexture}}
*{{ent|$surfaceprop}}
*{{ent|$envmap}}
*{{ent|$bumpmap}}
*{{ent|$detail}}
*{{ent|$selfillum}}
*{{ent|$model (VMT)|alt=$model}}
{{tip|If you ever need to use a space or tab character in a parameter value, you must wrap the whole value with "quote marks." You'll often see absolutely everything wrapped like this, but this is wholly unnecessary.}}
{{tip|To refresh a material in-game without restarting it, use the following console command: <tt>mat_reloadmaterial "vmt_name without .vmt and quotation marks"</tt>. Even though the <code>mat_reloadallmaterials</code> command exists, it's not recommended to use it, since various artifacts may appear. <tt>mat_reloadtextures</tt> is presented, too, but it seems to be very buggy.
For instance:
  mat_reloadmaterial combine_barricade_short01a
will reload every single material in the filesystem named <tt>combine_barricade_short01a</tt>, including all the custom content. For example: both <tt>materials/models/props_combine/combine_barricade_short01a.vmt</tt> and <tt>materials/models/props_metal_barricade/combine_barricade_short01a.vmt</tt> will be reloaded. This may appear very useful when writing proxies.}}


This will require some testing to get just right for each material. If your material has different levels of shininess, then adjust for the most reflective part of the material and then refer to the section on masking below. Here are some values to start you off closer to what you need:<br/>
== Utilities ==
;[ 1 1 1 ]
{{Xblahmt|4}}
:This is the highest level you would probably ever use. It might be used on a polished metal and will look almost as reflective as a mirror.<br/>
;[ .3 .3 .3 ]
:This is a good value for gloss paint.<br/>
;[ .07 .07 .07 ]
:This is a good value for concrete and sand. Shininess is just barely noticeable. Don’t use a reflection on concrete or sand if it doesn’t have a normal map, though. (Looks weird.)


'''3.''' You may want to adjust your reflection’s contrast with this line:<br/>
==See also==
"$envmapcontrast" 0.5
* [[Material]]
* [[Material Editor]]
* [[Creating Reflective Materials]]
* [[Creating PBR materials]]
* [[Adapting PBR Textures to Source]]
* [[:Category:List of Shader Parameters]]


The number should be between zero and one. Higher values will make the reflection look shinier without looking more reflective, if that makes sense. This might be useful for glass, which has more glaring reflections than other materials.
[[Category:Material System]]
 
[[Category:Tutorials]]
'''Note:''' For the reflection to work correctly in the game, your map must have at least one env_cubemap in it, and after you open the map in the game, open the [[console]] and type buildcubemaps.
 
The VMT for the example brick wall texture now might look like this:
<pre><nowiki>"LightmappedGeneric"
{
    "$basetexture" "walls/brickwall"
    "$surfaceprop" "brick"
    "$bumpmap" " walls/brickwall_normal"
    "$envmap" "env_cubemap"
    "$envmaptint" "[.5 .5 .5]"
}</nowiki></pre>
 
==Masking the reflection==
 
Some materials will have varying amounts of shininess. For example, a metal texture would not be very shiny wherever it's rusty. A mask will allow you to determine the reflectivity of each pixel of your texture.
 
'''1.''' Start by making the mask in grayscale at the same resolution as your original texture. The brightness of the mask will be multiplied by the opacity of the envmap, on top of the envmaptint. The rest of the steps depend on whether your material has a normal map:
 
'''2a.'''  ''Masking a material with a normal map''<br/>
Save the mask into the alpha channel of your normal map. Convert this new normal map to a VTF and replace the original normal map. Now add this line to your VMF:
 
<code>"$normalmapalphaenvmapmask" 1</code>
 
'''2b.''' ''Masking a material without a normal map''<br/>
Save the mask as a new TGA file (no alpha channel) with _mask at the end of the name. Convert it to a VTF and put it in the same directory as your texture. Add this line to your VMF:
 
<code>"$envmapmask" "__"</code>
 
and fill in the path and name of your mask.
 
For the example, perhaps we would want to make the bricks shinier than the plaster.  Since we already have a normalmap, we'd just embed the mask into the alpha channel of the normal map, as described in step 2a.  The VMT would now look like this:
<pre><nowiki>"LightmappedGeneric"
{
    "$basetexture" "walls/brickwall"
    "$surfaceprop" "brick"
    "$bumpmap" " walls/brickwall_normal"
    "$envmap" "env_cubemap"
    "$envmaptint" "[.5 .5 .5]"
    "$normalmapalphaenvmapmask" 1
}</nowiki></pre>
 
==Adding a parallax map (aka displacement map or height map)==
 
A parallax map will cause your flat material to look 3D. When you look at a parallax mapped material at an angle, the high points will obscure the low points behind them. This is only worthwhile for textures that have depth ranging at least a few centimeters, like deep-set bricks or stone. If you're not sure about using one, then don't bother.
 
'''1.''' Imagine your texture in 3D and create a new texture in grayscale where white corresponds to the pixels closest to you and black corresponds to pixels farthest from you. Save this as a TGA with _height at the end of the name and convert it to a VTF. Put it in the same directory as your texture.
 
'''2.''' Add these two lines to your VMF:
 
<code>"$parallaxmap" "__"</code><br/>
<code>"$parallaxmapscale" __</code>
 
and fill in the path and name of your parallax map on the first line and a number between zero and one on the second line. This number affects how deep the texture will look. 0.05 is an appropriate value for bricks.
 
If the bricks in the example brick wall texture were really thick and stuck out from the plaster, a parallax map might be appropriate.  We would create a VTF as described above named brickwall_height.vtf and place it with the other texture files.  The VMT would now look like this:
<pre><nowiki>"LightmappedGeneric"
{
    "$basetexture" "walls/brickwall"
    "$surfaceprop" "brick"
    "$bumpmap" " walls/brickwall_normal"
    "$parallaxmap" "walls/brickwall_height"
    "$parallaxmapscale" 0.05
    "$envmap" "env_cubemap"
    "$envmaptint" "[.5 .5 .5]"
    "$normalmapalphaenvmapmask" 1
}</nowiki></pre>
 
==Additional options==
 
;"$model" 1
:This line is necessary for model skins. Also note that the TGA should also be included in the same directory with the VTF and VMT for the modeler to skin with. Try to keep the skin for each model entirely in one texture—using multiple textures on a model is a resource hog. Remember that the shader type for models is always "VertexLitGeneric".
 
;"$decal" 1
:This is necessary for decals.
 
;"$selfillum" 1
:Adding this line will cause the texture to self-illuminate according to the alpha channel of your base texture. An example would be a Combine soldier’s helmet which is lit normally except for the eyes, which glow even in the dark.
 
;"$nocull" 1
:Add this line if you want your texture to be visible from both sides. This is only applicable for flat objects like glass or wire fences.
 
;"$alpha" 0.5
:Adding this line will make the texture translucent. The number can be anything between zero and one.
 
;"$color" "[1 1 1]"
:This will scale the color of the red, green, and blue components of your texture. You might use it if you wanted to use the same texture for multiple materials, such as various colors of the same looking glass.
 
Note: Everything in your VMT is going to be in quotes except for numbers that appear alone.
 
----
''See also''
 
[[Material System]]
 
[[Creating Materials]]

Latest revision as of 03:23, 27 January 2025

English (en)Español (es)Français (fr)日本語 (ja)한국어 (ko)Português do Brasil (pt-br)Русский (ru)中文 (zh)Translate (Translate)

This tutorial is a step-by-step guide to creating a brand new material, including the creation of the material's texture.

Creating a Texture

Any image file can be used as a texture, so long as both of its dimensions (height and width) are a power of two (1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096). To decide which to use, examine existing textures that fill the same role as yours. Higher resolutions lower performance but make an image sharper when viewed up close.

Different classes of object have different standard resolutions (e.g. character models' are very high). Check Valve's choices in hl2_textures_dir.vpk (from Half-Life 2) with GCFScape or VPKEdit if you are ever confused.

Note.pngNote:Texture source files should be saved in a lossless format like TGA pre-compile, to prevent unnecessary loss in quality. For textures without an alpha channel, PNG is also acceptable.
Note.pngNote:The file size limit is 33,554,432 bytes (32 MB). Compiling a .vtf over this amount will cause errors.

Converting the Texture

Textures must be converted to the Valve Texture Format before Source can use them. The tool Valve provides for this is VTEX. It's a command line tool with quite a few limitations, so the third-party tool VTFEdit VTFEdit (or VTFEdit Reloaded VTFEdit Reloaded) is preferable: it provides a graphical user interface, allows you to change a texture's properties without re-compiling it from scratch, accepts a wide range of image formats, and doesn't require the creation of script files for every texture. There are a handful of situations where you'll need to fall back on VTEX… but only a handful. Also, if you have textures that use transparency, it is recommended that you save them in TIFF format before importing to VTFedit as PNG transparency tends to have problems.

(There are VTF plug-ins that let you save to the format directly from Photoshop, GIMP, and Paint.NET, but this tutorial will not cover them as not everyone uses those tools.)

To import your texture with VTFEdit, use File > Import or press Ctrl+I. Select your image and you will be presented with the import screen:

VTFEdit's import screen

General settings

These settings are the most important. There are three:

Normal format
The color/compression format should be used if the texture is opaque.
Alpha format
The color/compression format should be used if the texture has an alpha channel.
Texture type
Importing more than one image determines what they will be used as (animation frames/cubemap faces/depth slices).

If you're making a plain and simple world texture you won't need to change any of these. If you're making a texture with fine gradient detail however, you'll need to choose a non-lossy compression mode.

Mipmap settings

Mipmaps are low-resolution versions of a texture that swap in when a surface is far away from the camera. They greatly reduce the amount of texture resizing needed, improving both performance and image quality. Mips are required for texture LOD to work.

Tip.pngTip:Textures that will appear in the 3D world should have mipmaps. To conserve memory, textures that will only be used in a 2D interface should not.

The following images demonstrate the various mipmap filters available in VTFEdit:

Normal map settings

These (mislabelled[How?]) settings allow you to automatically generate a bump map from your input image. You'll want to do this properly with an image editor for the material you ship, but the automated option is there if you want quick results or a base to work from.

Configuring and Saving

When you hit OK the input file is converted (there may be quite a lengthy pause for large images) and the output VTF appears. Now all that is left is configuring the texture with the options in the checkbox list on the left-hand side of the screen. See Valve Texture Format#Image_flags for descriptions of each.

Finally, save the file somewhere under your game or mod's \materials folder.

Creating a Material

Source doesn't access textures directly. Everything goes through a material.

Materials are script files that can be created in any text editor, but it's recommended that you use Notepad++ Notepad++ in conjunction with the community-made syntax highlighting rules. For your material to be detected, you must save it under your game or mod's \materials folder with the extension .vmt.

Note.pngNote:If you are creating materials and textures exclusively for a map for an existing mod, consider using BSPZIP\Packbsp\Pakrat\Compile Pal to package the material and texture files within the map file itself. This will prevent them from ever becoming lost.
Warning.pngWarning:Although your computer will let you save a file name that contains the % character, and VTFs work just fine with the character in the name, Hammer cannot handle VMTs whose names contain the % character.

Syntax

A material file looks like this:

<shader>
{
	<parameter> <value>
	...
}
LightmappedGeneric
{
	$basetexture coast\shingle_01
	$surfaceprop gravel
}

There are many shaders to choose from, but most materials will use either LightmappedGeneric (brushes) or VertexLitGeneric (models). The third most common shader is UnlitGeneric, which is used for UI materials and the occasional tool texture. A full list of shaders can be found here.

Parameters

For a list of all documented shader parameters, see Category:List of Shader Parameters.

With a shader chosen, you're onto parameters (also called commands). There are hundreds of options for what to put in a material so this article will only cover the most common, which are accepted by more or less all shaders. They are:

Tip.pngTip:If you ever need to use a space or tab character in a parameter value, you must wrap the whole value with "quote marks." You'll often see absolutely everything wrapped like this, but this is wholly unnecessary.
Tip.pngTip:To refresh a material in-game without restarting it, use the following console command: mat_reloadmaterial "vmt_name without .vmt and quotation marks". Even though the mat_reloadallmaterials command exists, it's not recommended to use it, since various artifacts may appear. mat_reloadtextures is presented, too, but it seems to be very buggy.

For instance:

 mat_reloadmaterial combine_barricade_short01a
will reload every single material in the filesystem named combine_barricade_short01a, including all the custom content. For example: both materials/models/props_combine/combine_barricade_short01a.vmt and materials/models/props_metal_barricade/combine_barricade_short01a.vmt will be reloaded. This may appear very useful when writing proxies.

Utilities

XBLAH's Modding Tool XBLAH's Modding Tool

See also