HQ Normal Maps: Difference between revisions

From Bohemia Interactive Community
Jump to navigation Jump to search
m (Text replacement - "[[Image:" to "[[File:")
m (Fix hl template usage error)
 
(One intermediate revision by the same user not shown)
Line 1: Line 1:
=HQ Normal Maps=
{{TOC|side}}
 
This technology allows normal maps compressed by various means in diverse shaders among others in shaders with specular map.
This technology allows normal maps compressed by various means in diverse shaders among others in shaders with specular map.
Normal maps may be represented as DXT1 or swizzled DXT5, two or three components.
Normal maps may be represented as DXT1 or swizzled DXT5, two or three components.
Line 13: Line 12:




==== New pixel shaders ====
== New pixel shaders ==


We got several pixel shaders which can work with HQ normal maps and also with specular map:
We got several pixel shaders which can work with HQ normal maps and also with specular map:


*NormalMapSpecularMap  
* NormalMapSpecularMap
*NormalMapDetailSpecularMap // function similar to NormalMapDiffuse - yet this name fits more
* NormalMapDetailSpecularMap // function similar to NormalMapDiffuse - yet this name fits more
*NormalMapMacroASSpecularMap  
* NormalMapMacroASSpecularMap
*NormalMapDetailMacroASSpecularMap  
* NormalMapDetailMacroASSpecularMap


From theirs title results what maps they use. First two match vertex shader NormalMap, second two NormalMapAS. Examples of use are here:
From theirs title results what maps they use. First two match vertex shader NormalMap, second two NormalMapAS. Examples of use are here:


specular[] = {0.5,0.5,0.5,0};
<syntaxhighlight lang="cpp">
specularPower = 10;
specular[] = { 0.5, 0.5 ,0.5, 0 };
PixelShaderID = "NormalMapSpecularMap";
specularPower = 10;
VertexShaderID = "NormalMap";
PixelShaderID = "NormalMapSpecularMap";
class Stage1
VertexShaderID = "NormalMap";
{
class Stage1
  texture="temp\NormalMap\normmap_NOHQ.tga";
{
  uvSource="tex";
texture = "temp\NormalMap\normmap_NOHQ.tga";
};
uvSource = "tex";
class Stage2
};
{
class Stage2
  texture="temp\NormalMap\specmap_SM.tga";
{
  uvSource="tex";
texture = "temp\NormalMap\specmap_SM.tga";
};
uvSource = "tex";
};
</syntaxhighlight>


specular[] = {0.5,0.5,0.5,0};
<syntaxhighlight lang="cpp">
specularPower = 10;
specular[] = { 0.5, 0.5, 0.5, 0 };
PixelShaderID = "NormalMapDetailSpecularMap";
specularPower = 10;
VertexShaderID = "NormalMap";
PixelShaderID = "NormalMapDetailSpecularMap";
class Stage1
VertexShaderID = "NormalMap";
{
class Stage1
  texture="temp\NormalMap\normmap_NOHQ.tga";
{
  uvSource="tex";
texture = "temp\NormalMap\normmap_NOHQ.tga";
};
uvSource = "tex";
class Stage2
};
{
class Stage2
  texture="temp\NormalMap\detmap_detail.paa";
{
  uvSource="tex";
texture = "temp\NormalMap\detmap_detail.paa";
  class uvTransform
uvSource = "tex";
  {
class uvTransform
    aside[] = {3,0,0};
{
    up[]   = {0,6,0};
aside[] = { 3, 0, 0 };
    dir[]   = {0,0,8};
up[] = { 0, 6, 0 };
    pos[]   = {0,0,0};
dir[] = { 0, 0, 8 };
  };
pos[] = { 0, 0, 0 };
};
};
class Stage3
};
{
class Stage3
  texture="temp\NormalMap\specmap_SM.tga";
{
  uvSource="tex";
texture="temp\NormalMap\specmap_SM.tga";
};
uvSource="tex";
};
</syntaxhighlight>


specular[] = {0.5,0.5,0.5,0};
<syntaxhighlight lang="cpp">
specularPower = 10;
specular[] = { 0.5, 0.5, 0.5, 0 };
PixelShaderID="NormalMapMacroASSpecularMap";
specularPower = 10;
VertexShaderID="NormalMapAS";
PixelShaderID = "NormalMapMacroASSpecularMap";
class Stage1
VertexShaderID = "NormalMapAS";
{
class Stage1
  texture="temp\domek\normmap_NOHQ.tga";
{
  uvSource="tex";
texture = "temp\domek\normmap_NOHQ.tga";
};
uvSource = "tex";
class Stage2
};
{
class Stage2
  texture="temp\domek\test02_MC.tga";
{
  uvSource="tex1";
texture="temp\domek\test02_MC.tga";
};
uvSource="tex1";
class Stage3
};
{
class Stage3
  texture="temp\domek\TestUV2_AS.tga";
{
  uvSource="tex1";
texture = "temp\domek\TestUV2_AS.tga";
};
uvSource = "tex1";
class Stage4
};
{
class Stage4
  texture="temp\domek\specmap_SM.tga";
{
  uvSource="tex";
texture = "temp\domek\specmap_SM.tga";
};
uvSource = "tex";
};
</syntaxhighlight>


specular[] = {0.5,0.5,0.5,0};
<syntaxhighlight lang="cpp">
specularPower = 10;
specular[] = { 0.5, 0.5, 0.5, 0 };
PixelShaderID="NormalMapDetailMacroASSpecularMap";
specularPower = 10;
VertexShaderID="NormalMapAS";
PixelShaderID = "NormalMapDetailMacroASSpecularMap";
class Stage1
VertexShaderID = "NormalMapAS";
{
class Stage1
  texture="temp\domek\normmap_NOHQ.tga";
{
  uvSource="tex";
texture = "temp\domek\normmap_NOHQ.tga";
};
uvSource = "tex";
class Stage2
};
{
class Stage2
  texture="temp\domek\detmap_detail.paa";
{
  uvSource="tex";
texture = "temp\domek\detmap_detail.paa";
  class uvTransform
uvSource = "tex";
  {
class uvTransform
    aside[] = {3,0,0};
{
    up[]   = {0,6,0};
aside[] = { 3, 0, 0 };
    dir[]   = {0,0,8};
up[] = { 0, 6, 0 };
    pos[]   = {0,0,0};
dir[] = { 0, 0, 8 };
  };
pos[] = { 0, 0, 0 };
};
};
class Stage3
};
{
class Stage3
  texture="temp\domek\test02_MC.tga";
{
  uvSource="tex1";
texture = "temp\domek\test02_MC.tga";
};
uvSource = "tex1";
class Stage4
};
{
class Stage4
  texture="temp\domek\TestUV2_AS.tga";
{
  uvSource="tex1";
texture = "temp\domek\TestUV2_AS.tga";
};
uvSource = "tex1";
class Stage5
};
{
class Stage5
  texture="temp\domek\specmap_SM.tga";
{
  uvSource="tex";
texture = "temp\domek\specmap_SM.tga";
};
uvSource = "tex";
};
</syntaxhighlight>


==== Specular map ====


Specular map is texture with extension "_SM" which contains material information how much specularity in what place and then also it can influence locally specular sharpness (power). Texture content is used this way:
== Specular map ==


*R - diffusion map
Specular map is texture with extension "_SM" which contains material information how much specularity in what place and then also it can influence locally specular sharpness (power).
*G - specular map
Texture content is used this way:
*B - power map


Specular power P which is used in the end is given by term '''P = specularPower * B''', where specularPower is set value in material.
* R - diffusion map
* G - specular map
* B - power map
 
Specular power P which is used in the end is given by term {{hl|P {{=}} specularPower * B}}, where specularPower is set value in material.
This mean if power map should not be set then it is needed adjust it to white and then only material's specular power is used.
This mean if power map should not be set then it is needed adjust it to white and then only material's specular power is used.


In order that shaders were simpler (faster), then inside them is inconsiderable multiplication of specular component with coefficient, which is derived in detail analysis (related to energy preservation of specular light) and which match term '''((specularPower * B + 1)/(specularPower + 1))'''.  
In order that shaders were simpler (faster), then inside them is inconsiderable multiplication of specular component with coefficient, which is derived in detail analysis (related to energy preservation of specular light) and which match term {{hl|((specularPower * B + 1) / (specularPower + 1))}}.
Practically this mean that in places where in map B isn't set to 1 then is needed to lower also G (the lower is R thereby lower must be also G)
Practically this mean that in places where in map B isn't set to 1 then is needed to lower also G (the lower is R thereby lower must be also G).


In order that sum of diffuse and specular component was constant (which applies on usual materials), it is imposed so called diffusion map in R component. That correspond to inversion of specular map before application of possible correction mentioned in previous paragraph.
In order that sum of diffuse and specular component was constant (which applies on usual materials), it is imposed so called diffusion map in R component.
That correspond to inversion of specular map before application of possible correction mentioned in previous paragraph.


From two above mentioned paragraphs results that for specular maps (SM also SMDI) it is necessary to use following TexView filter:
From two above mentioned paragraphs results that for specular maps (SM also SMDI) it is necessary to use following TexView filter:
Line 157: Line 167:
[[File:Specmap_SM.jpg]]
[[File:Specmap_SM.jpg]]


====== Optimized specular map onto bit depth ======
=== Optimized specular map onto bit depth ===
 
New texture arisen with extension _SMDI which replaces _SM. DI means that diffusion component (formerly in R) si here derived from specular inversion (DiffuseInverse). {{hl|_SMDI}} then writes constant 1 into R component.


New texture arisen with extension _SMDI which replaces _SM. DI means that diffusion component (formerly in R) si here derived from specular inversion (DiffuseInverse). _SMDI then writes constant 1 into R component.
This texture is possible to use in case when difusse map is just inversion of specular one.
Its application provides in part better compression and afterward diffusion component will have better bit depth (G is by one bit more precise). It's necessary to use corresponding shaders to the component.
* NormalMapSpecularDIMap
* NormalMapDetailSpecularDIMap
* NormalMapMacroASSpecularDIMap
* NormalMapDetailMacroASSpecularDIMap


This texture is possible to use in case when difusse map is just inversion of specular one. It's application provides in part better compression and afterward diffusion component will have better bit depth (G is by one bit more precise). It's necessary to use corresponding shaders to the component.
*NormalMapSpecularDIMap
*NormalMapDetailSpecularDIMap
*NormalMapMacroASSpecularDIMap
*NormalMapDetailMacroASSpecularDIMap


{{GameCategory|arma2|Editing}}
{{GameCategory|arma2|Editing}}

Latest revision as of 11:40, 22 March 2024

This technology allows normal maps compressed by various means in diverse shaders among others in shaders with specular map. Normal maps may be represented as DXT1 or swizzled DXT5, two or three components.

Motivation picture:

HQNormalSpecular.jpg

Confrontation of HQ and non HQ normal map:

HQvsNHQNormalMap.jpg


New pixel shaders

We got several pixel shaders which can work with HQ normal maps and also with specular map:

  • NormalMapSpecularMap
  • NormalMapDetailSpecularMap // function similar to NormalMapDiffuse - yet this name fits more
  • NormalMapMacroASSpecularMap
  • NormalMapDetailMacroASSpecularMap

From theirs title results what maps they use. First two match vertex shader NormalMap, second two NormalMapAS. Examples of use are here:

specular[] = { 0.5, 0.5 ,0.5, 0 };
specularPower = 10;
PixelShaderID = "NormalMapSpecularMap";
VertexShaderID = "NormalMap";
class Stage1
{
	texture = "temp\NormalMap\normmap_NOHQ.tga";
	uvSource = "tex";
};
class Stage2
{
	texture = "temp\NormalMap\specmap_SM.tga";
	uvSource = "tex";
};
specular[] = { 0.5, 0.5, 0.5, 0 };
specularPower = 10;
PixelShaderID = "NormalMapDetailSpecularMap";
VertexShaderID = "NormalMap";
class Stage1
{
	texture = "temp\NormalMap\normmap_NOHQ.tga";
	uvSource = "tex";
};
class Stage2
{
	texture = "temp\NormalMap\detmap_detail.paa";
	uvSource = "tex";
	class uvTransform
	{
		aside[] = { 3, 0, 0 };
		up[] = { 0, 6, 0 };
		dir[] = { 0, 0, 8 };
		pos[] = { 0, 0, 0 };
	};
};
class Stage3
{
	texture="temp\NormalMap\specmap_SM.tga";
	uvSource="tex";
};
specular[] = { 0.5, 0.5, 0.5, 0 };
specularPower = 10;
PixelShaderID = "NormalMapMacroASSpecularMap";
VertexShaderID = "NormalMapAS";
class Stage1
{
	texture = "temp\domek\normmap_NOHQ.tga";
	uvSource = "tex";
};
class Stage2
{
	texture="temp\domek\test02_MC.tga";
	uvSource="tex1";
};
class Stage3
{
	texture = "temp\domek\TestUV2_AS.tga";
	uvSource = "tex1";
};
class Stage4
{
	texture = "temp\domek\specmap_SM.tga";
	uvSource = "tex";
};
specular[] = { 0.5, 0.5, 0.5, 0 };
specularPower = 10;
PixelShaderID = "NormalMapDetailMacroASSpecularMap";
VertexShaderID = "NormalMapAS";
class Stage1
{
	texture = "temp\domek\normmap_NOHQ.tga";
	uvSource = "tex";
};
class Stage2
{
	texture = "temp\domek\detmap_detail.paa";
	uvSource = "tex";
	class uvTransform
	{
		aside[] = { 3, 0, 0 };
		up[] = { 0, 6, 0 };
		dir[] = { 0, 0, 8 };
		pos[] = { 0, 0, 0 };
	};
};
class Stage3
{
	texture = "temp\domek\test02_MC.tga";
	uvSource = "tex1";
};
class Stage4
{
	texture = "temp\domek\TestUV2_AS.tga";
	uvSource = "tex1";
};
class Stage5
{
	texture = "temp\domek\specmap_SM.tga";
	uvSource = "tex";
};


Specular map

Specular map is texture with extension "_SM" which contains material information how much specularity in what place and then also it can influence locally specular sharpness (power). Texture content is used this way:

  • R - diffusion map
  • G - specular map
  • B - power map

Specular power P which is used in the end is given by term P = specularPower * B, where specularPower is set value in material. This mean if power map should not be set then it is needed adjust it to white and then only material's specular power is used.

In order that shaders were simpler (faster), then inside them is inconsiderable multiplication of specular component with coefficient, which is derived in detail analysis (related to energy preservation of specular light) and which match term ((specularPower * B + 1) / (specularPower + 1)). Practically this mean that in places where in map B isn't set to 1 then is needed to lower also G (the lower is R thereby lower must be also G).

In order that sum of diffuse and specular component was constant (which applies on usual materials), it is imposed so called diffusion map in R component. That correspond to inversion of specular map before application of possible correction mentioned in previous paragraph.

From two above mentioned paragraphs results that for specular maps (SM also SMDI) it is necessary to use following TexView filter:

comment "define specular power";
sp = 10;
p = src pixel [u,v];
x = 1 - green p;
y = green p * ((sp * blue p + 1) / (sp + 1));
c = color[x,y,blue p,1];

Example of specular map:

Specmap SM.jpg

Optimized specular map onto bit depth

New texture arisen with extension _SMDI which replaces _SM. DI means that diffusion component (formerly in R) si here derived from specular inversion (DiffuseInverse). _SMDI then writes constant 1 into R component.

This texture is possible to use in case when difusse map is just inversion of specular one. Its application provides in part better compression and afterward diffusion component will have better bit depth (G is by one bit more precise). It's necessary to use corresponding shaders to the component.

  • NormalMapSpecularDIMap
  • NormalMapDetailSpecularDIMap
  • NormalMapMacroASSpecularDIMap
  • NormalMapDetailMacroASSpecularDIMap