Bump map: Difference between revisions

From Valve Developer Community
Jump to navigation Jump to search
m (→‎Photoshop or PaintShop Pro: plugin does not work in PSP9)
No edit summary
 
(87 intermediate revisions by 39 users not shown)
Line 1: Line 1:
[[category:material system]][[category:tutorials]]
{{LanguageBar}}
If your texture is supposed to have depth to it, adding a '''normal map''' (successor of the bump 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). While bump maps only used one channel to decode the height of each pixel, normal maps use all three:
* The blue channel decodes the height of the pixel (Z-axis)
* The red channel contains the horizontal slope (X-axis)
* The green channel includes the vertical slope (Y-axis)
With these 3 channels, every pixel has a normal vector, means the engine knows in which direction the pixel is facing and can thereby calculate shadows and highlights.


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]
[[File:Brickwall021a normalcompare.jpg|thumb|200px|A material's [[albedo]] (left) compared to its bump map.]]


The normal map should be created in the same dimensions as the image texture (color map) it will go with. There are a few options for how to create one, depending on the quality you want, your skill with various programs, or your patience.
[[File:Example of bump mapping.jpg|thumb|200px|The above material in-game.]]


==Normal Map from an image editing program==
Textures often called '''Bump Maps''', or '''Normal Maps''' are used to simulate three-dimensional details on a two-dimensional surface by manipulating its lighting.


===Photoshop or Paint Shop Pro===
{{note|
* Static props using bump maps can not be lit per-vertex, except in {{csgobranch}}. [[$lightmap]] is also incompatible with [[$bumpmap]].
* Bump maps cannot be used on normal [[decals]] and [[overlay]]s, except in {{csgobranch}}. In order for these to function properly, the surface that they are placed on must also have a bumpmap. Bumped "decals" can be created in any engine branch, regardless of underlying geometry, by using a [[Decals#brush_decals|brush or displacement with a $decal material]] instead.
}}


{{note|As of Jasc Paint Shop Pro version 9, the NVIDIA normal map plugin no longer works. Use Photoshop or GIMP instead.}}
== Format ==
<!-- Someone please test if it works with v. 8 -->


If you have Photoshop or Paint Shop Pro, you can use [[Wikipedia:NVIDIA|NVIDIA's]] normal map tools, available [http://developer.nvidia.com/object/photoshop_dds_plugins.html here]. 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. Be sure to change the texture back to RGB mode, or else the normal map tool will not work. 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.
Each pixel in a bump map contains the (x, y, z) coordinates that define a [[normal]]ized [[vector]].


[[Image:Beforenormal.jpg|thumb|left|Image texture (color map).]]
Because of this each color channel in a bump map has a meaning:
[[Image:afternormal.jpg|thumb|left|Normal map created from texture on left using NVIDIA's filter.]]<br style="clear:both">


===GIMP===
; Red
: Horizontal facing (X axis)
:* 0 = left
:* 128 = forward, or facing viewer
:* 255 = right
; Green
: Vertical facing (Y axis)
:* 0 = up
:* 128 = forward, or facing viewer
:* 255 = down
; Blue
: Height (Z axis).
:* 0 = facing 'in' to the texture, away from the viewer. This is a 'bad' value. Anything under 128 means that the surface should be facing away from the player, which is not possible.
:* 128 = maximum depth capable of receiving dynamic light. It's a bad idea to go under this.
:* 255 = facing 'out' of the texture towards the viewer.


[[Image:gimp_normal1.jpg|thumb|220px|Place the windows in a useful way]]Download the tool for GIMP [http://nifelheim.dyndns.org/%7ecocidius/normalmap/ here] and install it following the instructions in the readme.
After restarting GIMP, open a copy of the texture you want to create a normal map for and click:


<code>Filters -> Map -> Normalmap...</code>
{{note|A flat bump map should be [128, 128, 255]. <code>dev/flat_normal</code> is a flat bump map present in every game.}}


Before starting, you should click the <code>3D Preview</code> and place it next to the normalmap window. It will automatically update when you change your settings and will be a great help checking the results in GIMP. Select a shape similar to what your texture will be placed on ingame (e.g. a texture for brushes fits onto a cube whereas a modelskin might look better on a sphere). Make use of the UV scale to find a good setting.
The three channels represent a normal vector for every pixel which represents the direction that the pixel is facing in 3D space. This allows the engine to generate shadows and highlights on a two-dimensional surface, or give a 3D model more detail.
Now focus on the <code>Normalmap</code> window again. These are the most useful settings:
[[Image:gimp_normal2.jpg|thumb|220px|The 3D Preview is used to check the settings]]
* Filter - different ways to calculate your normal map. You'll have to try out which one works best for your texture
* Minimum Z - the lowest height on your normal map
* Scale - Use this to control the height of your surface. Results change when you choose a different filter
* Conversion - Let's you choose what is used to create the normal map. Max/Min RGB or only one color channel can be very helpful sometimes
''Checkboxes:''
* Wrap - Normal map will pattern seamless. Definitely use it for map textures!
* Invert X/Y - If your normal map seems to be upside down, this will help
Check the 3D Preview from several angles, also move the light around. When you've found the best setting, hit <code>OK</code> and your texture is converted to the normal map!
You can either go with that right away or rework it by hand. For example, you could duplicate the layer and use some overlay effects (Dodge, Addition, ...) or paint on the texture yourself if you want to create a flat part (RGB #7f7fff is flat).
[[Image:gimp_normal3.jpg|thumb|220px|left|Normal map was reworked by hand.]]<br style="clear:both">


==Normal Map from a Height Map==
A bump map is largely useless for really flat surfaces like smooth concrete or metal, but even smooth concrete sometimes has enough depth to it to make one worthwhile, especially if used in conjunction with a [[cubemap]].


==Normal Map from a 3D program==
[[file:normalmap.gif]]
*[http://developer.nvidia.com/object/melody_home.html NVIDIA Melody]
*[[NormalMapper]]
===XSI===
*ver 5.0: [http://www.softimage.com/products/xsi/v5/nfvt/default.asp Ultimapper]
*ver 4.x: GPU Surface FX2 {{note|You need XSI foundation or higher to take advantage of this feature, as the Mod Tool has a resolution limit.}}
*ver 3.5: GPU surface FX


The name has been changing, but the basic usage is the same:
== Creation ==


*Move the high resolution model over the low resolution model.
A bump map should be rendered in Tangent space and use vector directions X+ Y- Z+.
*Select the low resolution one.
*Select GPU Surface FX2 (or Ultimapper in ver 5.0) from Get>Property.
*In GPU Surface FX2 menu:
**Pick the high resolution model (or group).
**Make sure '''normal''' is checked.
**Change settings such as normal map resolution, path, sampling, as you want.
**If you are ready, click '''Regenerate''' button. XSI will make the normal map.
**To preview the result, set Preview Display and Hardware correctly and click '''Create Preview'''.
**'''Important:''' It is necessary to '''invert the green channel of the output file'''. If you don't do this, your up/down normals will appear '''inverted''' in the engine. The simplest way to do this in Photoshop is to open a channel window, (window:channel) select the green channel (which controls up/down), and press Ctrl+I.


===ZBrush2===
{{note|There are basically two sets of rules for normal maps: [[DirectX]] and [[OpenGL]]. Their interpretation of green channels are opposite. [[Source]] takes the former, whereas [[Source 2]] (even with DX11) takes the latter. Thus, the green channel may need to be inverted depending on the software used to create it. }}


==Getting the Normal Map in the Game==
=== Programs ===


<ol><li>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 _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.</li>
[[File:Test_bump.jpg|thumb|600px|Bump maps as created by various programs.]]
<li>Add this line to the VMT somewhere between the braces:<br/>


<pre>"$bumpmap" "texture name"</pre>
Various programs can automate the creation of bump maps, either by image analysis or by using 3D geometry the user provides.
and fill in the path and name of your normal map VTF. Here's an example VMT for a normal-mapped material:
 
<pre><nowiki>"LightmappedGeneric"
;2D
{
:[[Normal Map Creation in Photoshop or Paint Shop Pro|Photoshop or Paint Shop Pro]]
    "$basetexture" "walls/brickwall"
:[http://www.youtube.com/watch?v=WsFe-E-33IQ Substance Designer]
    "$surfaceprop" "brick"
:[[Normal Map Creation in The GIMP|The GIMP]]
    "$bumpmap" "walls/brickwall_normal"
:[http://www.youtube.com/watch?v=xDZDWvTUz-c nDo]
}</nowiki></pre>
:[http://filterforge.com/filters/8774.html Filter Forge]
:{{Xblahmt|4}}
:[https://charles.hollemeersch.net/njob/ nJob]
;3D
:[[Normal Map Creation in XSI|XSI]]
:[[Normal Map Creation in ZBrush|ZBrush]]
:[[Normal Map Creation in Lightwave|Lightwave]]
:[[Normal Map Creation in 3ds Max|3ds Max]]
:[[Normal Map Creation in Maya|Maya]]
:[[Normal Map Creation in Blender|Blender]]
:[[Materialize]]
:[http://www.nvidia.com/object/melody_home.html NVIDIA Melody]
:[http://planetpixelemporium.com/tutorialpages/normal2.html Cinema 4D]
:[[NormalMapper]]
:[http://xnormal.net/ xNormal]
;Other
:[https://cpetry.github.io/NormalMap-Online/ NormalMap Online]: A website for generating normal maps online.
:[https://sourceforge.net/projects/ssbumpgenerator/ SSBump Generator 5.3]: Despite the name, it can also be used to generate bumpmaps, not just [[$ssbump|self-shadowing bump maps]].
:[http://store.steampowered.com/app/325910/ Substance B2M3]: Previously known as BitMap2Material.
:[https://sites.google.com/site/ccdsurgeon/download/ InsaneBump]: Specifically made to be a free alternative to the now-superseded software "CrazyBump" (may trip antiviruses due to incompatibility)
 
=== Conversion ===
 
==== In [[VTFEdit]] ====
 
When converting your texture:
 
# Choose your image format. Uncompressed formats like BGR888 are higher-quality than compressed formats like DXT1, but be wary of file size.
# Check the "Normal map" box in the texture's flags list after the import is complete. It's about 1/5 of the way down the list.
 
{{tip|VTFEdit can automatically generate bump maps. See the bottom-right of the import screen.}}
 
==== In [[Vtex (Source 1)|Vtex]] ====


{{Note|Multiple materials can use the same normal map file.}}</li>
# Save your normal map as a [[TGA]]. Give it a name that ends in ''_normal''. The ''_normal'' at the end of the name will affect how [[Vtex (Source 1)|Vtex]] converts it. For the brick wall example, we would name the file <code>brickwall_normal.tga</code>.
# Add <code>nocompress 1</code> and <code>normal 1</code> to <texture filename>.txt in the same folder as your texture, then compile.


<li>When compiling your maps with vtex, Add this line to the <texture filename>.txt file in the same directory as your textures then compile with vtex.
=== Implementation ===
<br/>
 
<pre>"nocompress" "1"
Normal maps can be generated from a basetexture, using the Sobel Operator, by sampling the HSB Brightness of each pixel and adjoining pixel to determine the scale of the output Hue and Saturation values that are subsequently converted to RGB for the SetPixel operation.
"normal" "1"</pre></li></ol>
<syntaxhighlight lang=cpp>
Bitmap image = (Bitmap) Bitmap.FromFile(@"yourpath/yourimage.jpg");
int w = image.Width - 1;
int h = image.Height - 1;
float sample_l;
float sample_r;
float sample_u;
float sample_d;
float x_vector;
float y_vector;
Bitmap normal = new Bitmap(image.Width, image.Height);
for (int y = 0; y < w + 1; y++)
{
for (int x = 0; x < h + 1; x++)
{
if (x > 0) { sample_l = image.GetPixel(x - 1, y).GetBrightness(); }
else { sample_l = image.GetPixel(x, y).GetBrightness(); }
if (x < w) { sample_r = image.GetPixel(x + 1, y).GetBrightness(); }
else { sample_r = image.GetPixel(x, y).GetBrightness(); }
if (y > 1) { sample_u = image.GetPixel(x, y - 1).GetBrightness(); }
else { sample_u = image.GetPixel(x, y).GetBrightness(); }
if (y < h) { sample_d = image.GetPixel(x, y + 1).GetBrightness(); }
else { sample_d = image.GetPixel(x, y).GetBrightness(); }
x_vector = (((sample_l - sample_r) + 1) * .5f) * 255;
y_vector = (((sample_u - sample_d) + 1) * .5f) * 255;
Color col = Color.FromArgb(255, (int)x_vector, (int)y_vector, 255);
normal.SetPixel(x, y, col);
}
}
</syntaxhighlight>
See {{ent|$bumpmap}}.


==See also==
==See also==


[[Creating Materials]]
*{{ent|$ssbump}}: creation and usage of Valve's new self-shadowing bump maps.
 
*[http://planetpixelemporium.com/tutorialpages/normal.html An old article that explains normal mapping quite well]
[[Height2Normal]]
*[http://wiki.polycount.com/wiki/Normal_map Polycount wiki page about normal maps]
*[[Creating a Material]]


{{otherlang:en}} {{otherlang:en:jp|Creating Normal Maps:jp}}
[[Category:Material System]]
[[Category:Glossary]]
[[Category:Tutorials]]

Latest revision as of 08:47, 14 April 2025

English (en)Español (es)Français (fr)Português do Brasil (pt-br)Русский (ru)中文 (zh)Translate (Translate)
A material's albedo (left) compared to its bump map.
The above material in-game.

Textures often called Bump Maps, or Normal Maps are used to simulate three-dimensional details on a two-dimensional surface by manipulating its lighting.

Note.pngNote:
  • Static props using bump maps can not be lit per-vertex, except in CS:GO engine branch. $lightmap is also incompatible with $bumpmap.
  • Bump maps cannot be used on normal decals and overlays, except in CS:GO engine branch. In order for these to function properly, the surface that they are placed on must also have a bumpmap. Bumped "decals" can be created in any engine branch, regardless of underlying geometry, by using a brush or displacement with a $decal material instead.

Format

Each pixel in a bump map contains the (x, y, z) coordinates that define a normalized vector.

Because of this each color channel in a bump map has a meaning:

Red
Horizontal facing (X axis)
  • 0 = left
  • 128 = forward, or facing viewer
  • 255 = right
Green
Vertical facing (Y axis)
  • 0 = up
  • 128 = forward, or facing viewer
  • 255 = down
Blue
Height (Z axis).
  • 0 = facing 'in' to the texture, away from the viewer. This is a 'bad' value. Anything under 128 means that the surface should be facing away from the player, which is not possible.
  • 128 = maximum depth capable of receiving dynamic light. It's a bad idea to go under this.
  • 255 = facing 'out' of the texture towards the viewer.


Note.pngNote:A flat bump map should be [128, 128, 255]. dev/flat_normal is a flat bump map present in every game.

The three channels represent a normal vector for every pixel which represents the direction that the pixel is facing in 3D space. This allows the engine to generate shadows and highlights on a two-dimensional surface, or give a 3D model more detail.

A bump map is largely useless for really flat surfaces like smooth concrete or metal, but even smooth concrete sometimes has enough depth to it to make one worthwhile, especially if used in conjunction with a cubemap.

Normalmap.gif

Creation

A bump map should be rendered in Tangent space and use vector directions X+ Y- Z+.

Note.pngNote:There are basically two sets of rules for normal maps: DirectX and OpenGL. Their interpretation of green channels are opposite. Source takes the former, whereas Source 2 (even with DX11) takes the latter. Thus, the green channel may need to be inverted depending on the software used to create it.

Programs

Bump maps as created by various programs.

Various programs can automate the creation of bump maps, either by image analysis or by using 3D geometry the user provides.

2D
Photoshop or Paint Shop Pro
Substance Designer
The GIMP
nDo
Filter Forge
XBLAH's Modding Tool XBLAH's Modding Tool
nJob
3D
XSI
ZBrush
Lightwave
3ds Max
Maya
Blender
Materialize
NVIDIA Melody
Cinema 4D
NormalMapper
xNormal
Other
NormalMap Online: A website for generating normal maps online.
SSBump Generator 5.3: Despite the name, it can also be used to generate bumpmaps, not just self-shadowing bump maps.
Substance B2M3: Previously known as BitMap2Material.
InsaneBump: Specifically made to be a free alternative to the now-superseded software "CrazyBump" (may trip antiviruses due to incompatibility)

Conversion

In VTFEdit

When converting your texture:

  1. Choose your image format. Uncompressed formats like BGR888 are higher-quality than compressed formats like DXT1, but be wary of file size.
  2. Check the "Normal map" box in the texture's flags list after the import is complete. It's about 1/5 of the way down the list.
Tip.pngTip:VTFEdit can automatically generate bump maps. See the bottom-right of the import screen.

In Vtex

  1. Save your normal map as a TGA. Give it a name that ends in _normal. The _normal at the end of the name will affect how Vtex converts it. For the brick wall example, we would name the file brickwall_normal.tga.
  2. Add nocompress 1 and normal 1 to <texture filename>.txt in the same folder as your texture, then compile.

Implementation

Normal maps can be generated from a basetexture, using the Sobel Operator, by sampling the HSB Brightness of each pixel and adjoining pixel to determine the scale of the output Hue and Saturation values that are subsequently converted to RGB for the SetPixel operation.

Bitmap image = (Bitmap) Bitmap.FromFile(@"yourpath/yourimage.jpg");
int w = image.Width - 1;
int h = image.Height - 1;
float sample_l;
float sample_r;
float sample_u;
float sample_d;
float x_vector;
float y_vector;
Bitmap normal = new Bitmap(image.Width, image.Height);
for (int y = 0; y < w + 1; y++)
{
	for (int x = 0; x < h + 1; x++)
	{
		if (x > 0) { sample_l = image.GetPixel(x - 1, y).GetBrightness(); }
		else { sample_l = image.GetPixel(x, y).GetBrightness(); }
		if (x < w) { sample_r = image.GetPixel(x + 1, y).GetBrightness(); }
		else { sample_r = image.GetPixel(x, y).GetBrightness(); }
		if (y > 1) { sample_u = image.GetPixel(x, y - 1).GetBrightness(); }
		else { sample_u = image.GetPixel(x, y).GetBrightness(); }
		if (y < h) { sample_d = image.GetPixel(x, y + 1).GetBrightness(); }
		else { sample_d = image.GetPixel(x, y).GetBrightness(); }
		x_vector = (((sample_l - sample_r) + 1) * .5f) * 255;
		y_vector = (((sample_u - sample_d) + 1) * .5f) * 255;
		Color col = Color.FromArgb(255, (int)x_vector, (int)y_vector, 255);
		normal.SetPixel(x, y, col);
		}
	}

See $bumpmap.

See also