get view-space normal

You are an experienced programmer and have a problem with the engine, shaders, or advanced effects? Here you'll get answers.
No questions about C++ programming or topics which are answered in the tutorials!
Post Reply
kaos
Posts: 155
Joined: Tue Aug 12, 2008 8:25 pm
Location: Spain

get view-space normal

Post by kaos »

Color = tex2D(texNormal,IN.Texcoord1).xyz * 2 - 1;
Color.z is the depth
Color.z= sqrt( 1 - Color.x * Color.x - Color.y * Color.y );

return Color; (for test)

but the normal is static. How convert it to view-sapce ???

mul(Color,matWorldViewProjection) ??? I don't know

http://www.guerrilla-games.com/publicat ... _dev07.pdf
http://cmpmedia.vo.llnwd.net/o1/vault/g ... ghting.pdf
kaos
Posts: 155
Joined: Tue Aug 12, 2008 8:25 pm
Location: Spain

Post by kaos »

searching

Code: Select all

1	//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
2	// Zen GeometricBufferGen Shading Shader
3	//
4	// Copyright (C) 2008 - 2009 Matthew Alan Gray
5	//
6	//  This software is provided 'as-is', without any express or implied
7	//  warranty.  In no event will the authors be held liable for any damages
8	//  arising from the use of this software.
9	//
10	//  Permission is granted to anyone to use this software for any purpose,
11	//  including commercial applications, and to alter it and redistribute it
12	//  freely, subject to the following restrictions:
13	//
14	//  1. The origin of this software must not be misrepresented; you must not
15	//     claim that you wrote the original software. If you use this software
16	//     in a product, an acknowledgment in the product documentation would be
17	//     appreciated but is not required.
18	//  2. Altered source versions must be plainly marked as such, and must not be
19	//     misrepresented as being the original software.
20	//  3. This notice may not be removed or altered from any source distribution.
21	//
22	//  Matthew Alan Gray mgray@indiezen.org
23	//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
24	
25	//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
26	// Vertex Shader input struct
27	//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
28	struct VIn
29	{
30	    float4 pos      : POSITION;     // World space vertex position
31	
32	    float3 n        : NORMAL;       // World space vertex normal
33	
34	    float3 b        : BINORMAL;     // World space vertex binormal
35	
36	    float3 t        : TANGENT;      // World space vertex tangent
37	
38	    float2 uv       : TEXCOORD0;    // Vertex Texture UV coordinates
39	};
40	
41	//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
42	// Vertex Shader output struct
43	//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
44	struct VOut
45	{
46	    float4 pos              : POSITION;     // Clip space vertex position
47	
48	    float4 hpos             : TEXCOORD0;    // Clip space vertex position
49	 
50	    float2 uv               : TEXCOORD1;    // Vertex Texture UV coordinates
51	
52	    float3x3 tangentToView  : TEXCOORD2;    // Vertex tangent space to
53	                                            // view space transformation matrix
54	};
55	
56	//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
57	// GeometricBufferGen Vertex Shader
58	// 
59	//  Uniform Variables
60	//   * _worldView - World View matrix
61	//   * _inverseTransposeWorldView - Inverse Transpose World View matrix
62	//   * _worldViewProjection - World View Projection matrix
63	//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
64	VOut GeometricBufferGen_vs(VIn _in,
65	                           uniform float4x4 _worldView,
66	                           uniform float3x3 _inverseTransposeWorldView,
67	                           uniform float4x4 _worldViewProjection)
68	{
69	    VOut OUT = (VOut)0;
70	
71	    // Transform the world space coordinates into homogeneous clip space.
72	    OUT.pos = mul( _worldViewProjection, _in.pos );
73	    OUT.hpos = OUT.pos;
74	
75	    // Pass uv texture coordinates to the pixel shader.
76	    OUT.uv = _in.uv;
77	
78	    // Calculate tangent space to view space matrix.
79	    OUT.tangentToView[0] = mul( _inverseTransposeWorldView, _in.t );
80	    OUT.tangentToView[1] = mul( _inverseTransposeWorldView, _in.b );
81	    OUT.tangentToView[2] = mul( _inverseTransposeWorldView, _in.n );
82	
83	    return OUT;
84	}
85	
86	//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
87	// Pixel Shader input struct
88	//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
89	struct PIn
90	{
91	    float4 hpos             : TEXCOORD0;    // Clip space pixel position
92	
93	    float2 uv               : TEXCOORD1;    // Pixel UV texture coordinates
94	
95	    float3x3 tangentToView  : TEXCOORD2;    // Pixel tangent space to world
96	                                            // view transformation matrix
97	};
98	
99	//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
100	// Pixel Shader output struct
101	//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
102	struct POut
103	{
104	    float depthBuf              : DEPTH;    // Depth/Stencil Render Target
105	
106	    float4 lightBuf             : COLOR0;   // Accumulated Light Render Target
107	
108	    float2 normalBuf            : COLOR1;   // Normal Map Render Target
109	
110	    float4 motionSpecularityBuf : COLOR2;   // Motion/Specularity Render Target
111	
112	    float4 diffuseOcclusionBuf  : COLOR3;   // Diffuse/Occlusion Render Target
113	};
114	
115	//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
116	// GeometricBufferGen Pixel Shader
117	//
118	//  Uniform Variables
119	//   * _lightMap - initialization accumulated light map (sampler2D)
120	//   * _normalMap - tangent space normal map (sampler2D)
121	//   * _specularMap - specular power/roughness and intensity map (sampler2D)
122	//   * _diffuseMap - diffuse and occlusion map (sampler2D)
123	//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
124	POut GeometricBufferGen_ps(PIn _in,
125	                           uniform sampler2D _lightMap,
126	                           uniform sampler2D _normalMap,
127	                           uniform sampler2D _specularMap,
128	                           uniform sampler2D _diffuseMap)
129	{
130	    POut OUT = (POut)0;
131	
132	    // Compute the pixel depth
133	    OUT.depthBuf = _in.hpos.z;
134	
135	    // Initialize the light accumulation pixel
136	    OUT.lightBuf = tex2D( _lightMap, _in.uv );
137	
138	    // Compute the normal map pixel
139	    // @{
140	    float3 n = tex2D( _normalMap, _in.uv ).xyz * 2.0 - 1.0;
141	
142	    // Transform normal from tangent space to view space
143	    n = normalize( mul( _in.tangentToView, n ) );
144	
145	    OUT.normalBuf.xy = n.xy;
146	    // @}
147	
148	    // Initialize the motion/specularity pixel
149	    OUT.motionSpecularityBuf = tex2D( _specularMap, _in.uv );
150	
151	    // Initialize the diffuse/occlusion pixel
152	    OUT.diffuseOcclusionBuf = tex2D( _diffuseMap, _in.uv );
153	
154	    return OUT;
155	}
How get t,b,n in correct world space ?

float3 Normal = mul(matWorldInverse,IN.Normal);
float3 Tangent = float3(abs(Normal.y)+abs(Normal.z),abs(Normal.x),0);
float3 Binormal = cross(Tangent,Normal);
Mel
Competition winner
Posts: 2292
Joined: Wed May 07, 2008 11:40 am
Location: Granada, Spain

Post by Mel »

Olvida eso de la generacion del tangent space en el shader.

Irrlicht es capaz de pasar la tangente y la binormal, el problema es que no los pasa en TANGENT0 o BINORMAL0, sino en TEXCOORD1 y TEXCOORD2, respectivamente. Eso si, tienes que calcular el tangent space en la malla.

Code: Select all

VS_INPUT{
...
float3 normal     :   NORMAL0;
float3 tangent    :   TEXCOORD1;//fijate aqui!
float3 binormal  :   TEXCOORD2; //OJO! no estan donde se supone que deberian!
...
};
tienes que pasar la normal, la binormal y la tangente al pixel shader. Asi que en el vertex shader hacemos esto...

Code: Select all

...
OUT.normal = mul(IN.normal,matWorldInv);
OUT.tangent = mul(IN.normal,matWorldInv);
OUT.binormal = mul(IN.normal,matWorldInv);
...
Con respecto a lo otro, no se, miraré los pdfs a ver que sale.
"There is nothing truly useless, it always serves as a bad example". Arthur A. Schmitt
kaos
Posts: 155
Joined: Tue Aug 12, 2008 8:25 pm
Location: Spain

Post by kaos »

gracias mel, este es el shader en hlsl.

I think that work.

Code: Select all


float4x4 matWorldViewInv;
float4x4 matWorlViewProjection;

//--------------------------------------------

sampler2D tex1 : register(s0);

//--------------------------------------------
struct VS_INPUT
{
   float4 Position         :  POSITION0;
   float3 Normal           :  NORMAL0;
   float2 Texcoord1        :  TEXCOORD0;
   float3 Tangent          :  TEXCOORD1;
   float3 Binormal         :  TEXCOORD2;
};
//--------------------------------------------
struct VS_OUTPUT
{
   float4 Position         :  POSITION0;
   float2 Texcoord1        :  TEXCOORD0;
   float3 vNormal          :  TEXCOORD1;
   float3 vTangent         :  TEXCOORD2;
   float3 vBinormal        :  TEXCOORD3;
   float3x3 tangentToView  :  TEXCOORD4;
};
//--------------------------------------------
struct PS_INPUT
{
   float2 Texcoord1        :  TEXCOORD0;
   float3 vNormal          :  TEXCOORD1;
   float3 vTangent         :  TEXCOORD2;
   float3 vBinormal        :  TEXCOORD3;
   float3x3 tangentToView  :  TEXCOORD4;
};
//--------------------------------------------
VS_OUTPUT main_vs( VS_INPUT IN )
{

   VS_OUTPUT OUT;

   OUT.Texcoord1 = IN.Texcoord1;

   OUT.Position  = mul(IN.Position,matWorlViewProjection);

   OUT.vNormal   = mul(matWorldViewInv,IN.Normal);
   OUT.vTangent  = mul(matWorldViewInv,IN.Tangent);
   OUT.vBinormal = mul(matWorldViewInv,IN.Binormal);

   OUT.tangentToView[0] = OUT.vTangent;
   OUT.tangentToView[1] = OUT.vBinormal;
   OUT.tangentToView[2] = OUT.vNormal;

   return( OUT );

}
//--------------------------------------------
float4 main_ps( PS_INPUT IN ) : COLOR0
{

	float4 Color;

	Color.w    = 1;

	Color.xyz  = tex2D(tex1,IN.Texcoord1).xyz * 2 - 1;

	Color.xyz = normalize(mul(Color.xyz,IN.tangentToView));

	Color.z = sqrt( 1 - Color.x * Color.x - Color.y * Color.y );

	return Color;

}
//--------------------------------------------

Can I work with 2 uvmaps when I to use createMeshWithTangents, how?. :(
devsh
Competition winner
Posts: 2057
Joined: Tue Dec 09, 2008 6:00 pm
Location: UK
Contact:

Post by devsh »

no va a funcionar, porque usted es la regeneración de la componente Z de normal

usted no será capaz de regenerar el normal si Z es negativo

lo que tiene que tener la normal en viewspace por escrito a la textura

Estoy asumiendo que usted tiene un deferred renderer?

no funcionarà, ja que s'estan regenerant el component Z normal
vostè no serà capaç de regenerar el normal si Z és negatiu
el que ha de tenir la normal en viewspace per escrit a la textura
Estic assumint que vostè té un deferred renderer?

Ce ne marchera pas, parce que vous régénére de la composante Z de normale
vous ne serez pas en mesure de régénérer la normale, si Z est négatif. Donc vous besoin avoir la normale dans le viewspace écrite à la texture
Je suppose que vous avez un deferred renderer?

To nie zadziala, poniewaz regenerujesz component Z normal'a. Ty nie bedziesz wstanie zregenerowac go jesli Z jest negatywne. Dlatego musisz miec normal w viewspace zapisany w teksturze. Zakladam ze masz deferred renderer?

Ni fydd yn gweithio, am eich bod yn adfywio'r gydran Z arferol
ni fyddwch yn gallu adfywio arferol os yn negyddol Z
felly mae'n rhaid i chi gael y arferol mewn viewspace ysgrifenedig i'r gwead
Yr wyf yn tybio bod gennych renderer gohiriedig

Right how many more languages do you want this in?
kaos
Posts: 155
Joined: Tue Aug 12, 2008 8:25 pm
Location: Spain

Post by kaos »

My english it's very bad so I answered to mel in spanih, sorry if you have any problem I din't want to offend anybody.

If z in view space is negative, is a backaface??
devsh
Competition winner
Posts: 2057
Joined: Tue Dec 09, 2008 6:00 pm
Location: UK
Contact:

Post by devsh »

No I dont get offended by people speaking their languages because I would be a racist prick like the majority of the english population between the ages of 12 to 18, but keep in mind that the post will be searched by people with similar problems. Now it would be useful to provide an english translation for all the explanations, because google translate does have real issues.

And when I stuck it in g_translate I got a vague idea, you are not doing deferred but normal map reading, the Z reconstruction method is fine but it will give you extra computation time also the depth map MAY not be normalized (bad interpolation/filtering, although most of the time it should be correct). The only time it comes useful is if you use the LUMINANCE format for your normal map (just two 8 bit values) for compression. Even when using the relief map you will still have 1 channel free and not used, so no performance or memory boost. The method is 100% correct though so you can use it, as all normal maps face towards the camera (Z or Y positive) :)
macron12388
Posts: 126
Joined: Wed Sep 29, 2010 8:23 pm

Post by macron12388 »

I can provide a translation. I speak English mostly through the internet, and Spanish with my parents...
macron12388
Posts: 126
Joined: Wed Sep 29, 2010 8:23 pm

Post by macron12388 »

Mel wrote: Forget about the generation of the tangent space in the shader.

Irrlicht is capable of passing the tangent and binormal, the problem is that it doesn't pass them in TANGENT0 or BINORMAL0, rather it passes them in TEXCOORD1 and TEXTCOORD2, respectively. So, you have to calculate the tangent space manually (??? I think this is slang I am not familiar with...)

Code: Select all

VS_INPUT{
...
float3 normal     :   NORMAL0;
float3 tangent    :   TEXCOORD1;//Look here!
float3 binormal  :   TEXCOORD2; //Keep an eye out! They aren't where //you would expect them to be!
...
};
You have to pas the normal, binormal and the tangent to the pixel shader. This is what you do in the pixel shader...

Code: Select all

...
OUT.normal = mul(IN.normal,matWorldInv);
OUT.tangent = mul(IN.normal,matWorldInv);
OUT.binormal = mul(IN.normal,matWorldInv);
...
Concerning everything else, I don't know, I'll check the pdfs to see what comes out.
First one translated.
Last edited by macron12388 on Fri Dec 17, 2010 12:00 am, edited 1 time in total.
macron12388
Posts: 126
Joined: Wed Sep 29, 2010 8:23 pm

Post by macron12388 »

kaos wrote:Thanks mel, this is the shader in hlsl

I think that'll work.

Code: Select all


float4x4 matWorldViewInv;
float4x4 matWorlViewProjection;

//--------------------------------------------

sampler2D tex1 : register(s0);

//--------------------------------------------
struct VS_INPUT
{
   float4 Position         :  POSITION0;
   float3 Normal           :  NORMAL0;
   float2 Texcoord1        :  TEXCOORD0;
   float3 Tangent          :  TEXCOORD1;
   float3 Binormal         :  TEXCOORD2;
};
//--------------------------------------------
struct VS_OUTPUT
{
   float4 Position         :  POSITION0;
   float2 Texcoord1        :  TEXCOORD0;
   float3 vNormal          :  TEXCOORD1;
   float3 vTangent         :  TEXCOORD2;
   float3 vBinormal        :  TEXCOORD3;
   float3x3 tangentToView  :  TEXCOORD4;
};
//--------------------------------------------
struct PS_INPUT
{
   float2 Texcoord1        :  TEXCOORD0;
   float3 vNormal          :  TEXCOORD1;
   float3 vTangent         :  TEXCOORD2;
   float3 vBinormal        :  TEXCOORD3;
   float3x3 tangentToView  :  TEXCOORD4;
};
//--------------------------------------------
VS_OUTPUT main_vs( VS_INPUT IN )
{

   VS_OUTPUT OUT;

   OUT.Texcoord1 = IN.Texcoord1;

   OUT.Position  = mul(IN.Position,matWorlViewProjection);

   OUT.vNormal   = mul(matWorldViewInv,IN.Normal);
   OUT.vTangent  = mul(matWorldViewInv,IN.Tangent);
   OUT.vBinormal = mul(matWorldViewInv,IN.Binormal);

   OUT.tangentToView[0] = OUT.vTangent;
   OUT.tangentToView[1] = OUT.vBinormal;
   OUT.tangentToView[2] = OUT.vNormal;

   return( OUT );

}
//--------------------------------------------
float4 main_ps( PS_INPUT IN ) : COLOR0
{

	float4 Color;

	Color.w    = 1;

	Color.xyz  = tex2D(tex1,IN.Texcoord1).xyz * 2 - 1;

	Color.xyz = normalize(mul(Color.xyz,IN.tangentToView));

	Color.z = sqrt( 1 - Color.x * Color.x - Color.y * Color.y );

	return Color;

}
//--------------------------------------------

How can I work with 2 uvmaps when I use createMeshWithTangents. :(
Second one translated.
Mel
Competition winner
Posts: 2292
Joined: Wed May 07, 2008 11:40 am
Location: Granada, Spain

Post by Mel »

I am sorry, i spoke in spanish for his clarity's sake.

I did some tests, and THIS works exactly as the one Guerrilla uses in Killzone2: I am picking your example to save some writting :lol:

Code: Select all

float4x4 matViewInv; //inverse of the view matrix!
float4x4 matWorlViewProjection;

//--------------------------------------------

sampler2D tex1 : register(s0);//This is the normal map.

//--------------------------------------------
struct VS_INPUT
{
   float4 Position         :  POSITION0;
   float3 Normal           :  NORMAL0;
   float2 Texcoord1        :  TEXCOORD0;
   float3 Tangent          :  TEXCOORD1;
   float3 Binormal         :  TEXCOORD2;
};
//--------------------------------------------
struct VS_OUTPUT
{
   float4 Position         :  POSITION0;
   float2 Texcoord1        :  TEXCOORD0;
   float3 vNormal          :  TEXCOORD1;
   float3 vTangent         :  TEXCOORD2;
   float3 vBinormal        :  TEXCOORD3;
   float3x3 tangentToView  :  TEXCOORD4;
};
//--------------------------------------------
struct PS_INPUT
{
   float2 Texcoord1        :  TEXCOORD0;
   float3 vNormal          :  TEXCOORD1;
   float3 vTangent         :  TEXCOORD2;
   float3 vBinormal        :  TEXCOORD3;
   float3x3 tangentToView  :  TEXCOORD4;
};
//--------------------------------------------
VS_OUTPUT main_vs( VS_INPUT IN )
{

   VS_OUTPUT OUT;

   OUT.Texcoord1 = IN.Texcoord1;

   OUT.Position  = mul(IN.Position,matWorlViewProjection);

   OUT.vNormal   = mul(matViewInv,IN.Normal);
   OUT.vTangent  = mul(matViewInv,IN.Tangent);
   OUT.vBinormal = mul(matViewInv,IN.Binormal);

   OUT.tangentToView[0] = OUT.vTangent;
   OUT.tangentToView[1] = OUT.vBinormal;
   OUT.tangentToView[2] = OUT.vNormal;

   return( OUT );

}
//--------------------------------------------
float4 main_ps( PS_INPUT IN ) : COLOR0
{
   float4 Color;

   Color.w    = 1;
   Color.xyz  = tex2D(tex1,IN.Texcoord1).xyz * 2 - 1;
   Color.xyz = normalize(mul(Color.xyz,IN.tangentToView));

   return float4(Color.xy,-Color.z,1);

  //Z is actually calculated, but not shown, you have to revert its value because it is negative. You must keep that in mind also.
}
//--------------------------------------------
This code is pretty straight. The good thing is that the values of this shader are suitable for an ARGB 32 bit texture. I think it should be very useful to have an OpenGL counterpart.
Last edited by Mel on Fri Dec 17, 2010 12:09 am, edited 1 time in total.
"There is nothing truly useless, it always serves as a bad example". Arthur A. Schmitt
macron12388
Posts: 126
Joined: Wed Sep 29, 2010 8:23 pm

Post by macron12388 »

Mel wrote:I am sorry, i spoke in spanish for his clarity's sake.
I really don't think it's too big of a problem, I hope my translation still retained the meaning of your explanation?
Mel
Competition winner
Posts: 2292
Joined: Wed May 07, 2008 11:40 am
Location: Granada, Spain

Post by Mel »

Yep, mostly.
"There is nothing truly useless, it always serves as a bad example". Arthur A. Schmitt
Post Reply