16
ShaderX5 2.6 Normal Mapping without Precomputed Tangents Christian Schuler, Phenomic ShaderStudy 2013.03.18 황황황 http://cafe.naver.com/shader

Shaderx5 2.6normalmappingwithoutprecomputedtangents 130318 (1)

Embed Size (px)

DESCRIPTION

 

Citation preview

Page 1: Shaderx5 2.6normalmappingwithoutprecomputedtangents 130318 (1)

ShaderX5 2.6

Normal Mapping without Precomputed Tangents

Christian Schuler, Phenomic

ShaderStudy 2013.03.18 황규석 http://cafe.naver.com/shader

Page 2: Shaderx5 2.6normalmappingwithoutprecomputedtangents 130318 (1)

Introduction

TBN Matrix(Tangent Frames) 를 Pixel Shader 에서 실시간으로 계산하는 방법

장점 - Vertex attributes 에 Tangent Frames 를 넣어 줄 필요가 없다

• Band width, Memory, Complexity 감소• 그래픽 디자이너가 툴에서 이것을 신경 쓸 필요가 없다

단점 - Pixel Shader 에서의 부하 , Optimization 필수

Cotangent Frames

- More optimization

Page 3: Shaderx5 2.6normalmappingwithoutprecomputedtangents 130318 (1)

TBN matrix

Page 4: Shaderx5 2.6normalmappingwithoutprecomputedtangents 130318 (1)

Normal Texture Mapping

©http://marupeke296.com

Normal 벡터를 Texture 좌표계 ( 공간 ) 에서 Local 좌표계 ( 공간 )로 변환

new = [dot(old, X), dot(old, Y), dot(old, Z)](X, Y, Z 는 new 좌표계에서 표현되는 old 좌표계 basis vectors, e.g. T, B, N)

Page 5: Shaderx5 2.6normalmappingwithoutprecomputedtangents 130318 (1)

Tangents to a surface

Position 벡터 (p1, p2) 와 Texture 좌표 벡터 (u1, u2, v1, v2) 를 이용해 Tangent 벡터 (T, B) 계산

Page 6: Shaderx5 2.6normalmappingwithoutprecomputedtangents 130318 (1)

// A code snippet to perform normal perturbation using a tangent-space normal mapfloat3 perturb_normal(float3 T, float3 B, float3 N, float2 texcoord){ // Build a tangent frame as float3x3 for convenience float3x3 tangent_frame = float3x3(T, B, N);

// Read the perturbed normal from the normal map float3 perturbed_normal = tex2D(normalmap, texcoord);

// Sign-expand (for a normal map in unsigned RGB format) perturbed_normal = 2 * perturbed_normal – 1;

// And transform the perturbed normal out of tangent space // (into whatever space T, B and N were originally expressed in, usually world). return normalize( mul( perturbed_normal, tangent_frame));}

Tangent space Normal mapping

Page 7: Shaderx5 2.6normalmappingwithoutprecomputedtangents 130318 (1)

// A function that takes an interpolated surface normal N, a position vector p, // and texture coordinates u and v and returns a complete tangent frame that is // ready to be used in lighting calculations (46 pixel shader instructions)float3x3 compute_tangent_frame(float3 N, float3 p, float2 uv){ // Get edge vectors of the pixel triangle float3 dp1 = ddx(p); // 가로 방향의 옆 픽셀과의 Position 변화량 float3 dp2 = ddy(p); // 세로 방향의 옆 픽셀과의 Position 변화량 float2 duv1 = ddx(uv); // 가로 방향의 옆 픽셀과의 UV 값 변화량 float2 duv2 = ddy(uv); // 세로 방향의 옆 픽셀과의 UV 값 변화량 // Solve the linear system float3x3 M = float3x3(dp1, dp2, cross(dp1, dp2)); float3x3 inverseM = invert_3x3(M); float3 T = mul(inverseM, float3(duv1.x, duv2.x, 0)); float3 B = mul(inverseM, float3(duv1.y, duv2.y, 0));

// Construct tangent frame // (* see discussion regarding the square patch assumption) float maxLength = max(length(T), length(B)); return float3x3 (T / maxLength, B / maxLength, N);}

float3x3 invert_3x3(float3x3 M){ float det = dot( cross(M[0], M[1]), M[2] ); float3x3 T = transpose(M); return float3x3( cross(T[1], T[2]), cross(T[2], T[0]), cross(T[0], T[1]) ) / det;}

Moving to the Pixel Sahder

Page 8: Shaderx5 2.6normalmappingwithoutprecomputedtangents 130318 (1)
Page 9: Shaderx5 2.6normalmappingwithoutprecomputedtangents 130318 (1)

// Optimization 1: // normalize T and B and spare the determinant. // (31 pixel shader instructions)float3x3 compute_tangent_frame_01(float3 N, float3 p, float2 uv){ // Get edge vectors of the pixel triangle float3 dp1 = ddx(p); float3 dp2 = ddy(p); float2 duv1 = ddx(uv); float2 duv2 = ddy(uv); // Solve the linear system float3x3 M = float3x3(dp1, dp2, cross(dp1, dp2)); float3x3 inverseM = invert_3x3_nodet(M); float3 T = mul(inverseM, float3(duv1.x, duv2.x, 0)); float3 B = mul(inverseM, float3(duv1.y, duv2.y, 0));

// Construct tangent frame return float3x3(normalize(T), normalize(B), N);}

float3x3 invert_3x3_nodet(float3x3 M){ float3x3 T = transpose(M); return float3x3( cross(T[1], T[2]), cross(T[2], T[0]), cross(T[0], T[1]) );}

Optimization 1

Page 10: Shaderx5 2.6normalmappingwithoutprecomputedtangents 130318 (1)

// Optimization 2: // exploits the zero components found in the solution vectors and collapses// a hidden double transpose // (17 pixel shader instructions)float3x3 compute_tangent_frame_02(float3 N, float3 p, float2 uv){ // Get edge vectors of the pixel triangle float3 dp1 = ddx(p); float3 dp2 = ddy(p); float2 duv1 = ddx(uv); float2 duv2 = ddy(uv); // Solve the linear system float3x3 M = float3x3(dp1, dp2, cross(dp1, dp2)); float3x3 inversetransposeM = float2x3( cross(M[1], M[2]), cross(M[2], M[0]) ); //inversetranspose =

original float3 T = mul(float2(duv1.x, duv2.x), inversetransposeM); float3 B = mul(float2(duv1.y, duv2.y), inversetransposeM);

// Construct tangent frame return float3x3(normalize(T), normalize(B), N);}

Optimization 2

Page 11: Shaderx5 2.6normalmappingwithoutprecomputedtangents 130318 (1)

// Optimization 3:// assume M is orthogonal and exploits the fact that we have made an inverse transpose explicit. // (14 pixel shader instructions)float3x3 compute_tangent_frame_03(float3 N, float3 p, float2 uv){ // Get edge vectors of the pixel triangle float3 dp1 = ddx(p); float3 dp2 = ddy(p); float2 duv1 = ddx(uv); float2 duv2 = ddy(uv); // Solve the linear system // (not much solving is left going here) float2x3 M = float2x3(dp1, dp2); float3 T = mul(float2(duv1.x, duv2.x), M); float3 B = mul(float2(duv1.y, duv2.y), M);

// Construct tangent frame return float3x3(normalize(T), normalize(B), N);}

Optimization 3

Page 12: Shaderx5 2.6normalmappingwithoutprecomputedtangents 130318 (1)
Page 13: Shaderx5 2.6normalmappingwithoutprecomputedtangents 130318 (1)

Conclusion

TBN matrix 계산을 Pixel shader 에서 낮은 비용으로 하는 방법 제공함

Vertex 속성에서 Tangent frames 를 제거할 수 있지만 픽셀셰이더에서 부하가 증가

텍스처 좌표 공간에서의 procedural 처리도 가능한 방법

추가적으로 Cotangent frames 를 이용한 방법을 블로그에 소개하고 있음

Page 14: Shaderx5 2.6normalmappingwithoutprecomputedtangents 130318 (1)

A vector v (red) represented by tangent basis vectors (yellow, left: e1, e2, e3) to the coordinate curves (black), · dual basis, covector basis, or cobasis (blue, right: e1, e2, e3 ), normal vectors to coordinate surfaces (grey), in 3D general curvilinear coordinates (q1, q2, q3), a tuple of numbers to define point in a position space. Note: the basis and cobasis do not coincide unless the basis is orthogonal.

Tangent and Contangent basis vectors

©wikipedia

Page 15: Shaderx5 2.6normalmappingwithoutprecomputedtangents 130318 (1)

// compute contangent framesmat3 contangent_frame(vec3 N, vec3 p, vec2 uv){ // Get edge vectors of the pixel triangle vec3 dp1 = dFdx(p); vec3 dp2 = dFdy(p); vec2 duv1 = dFdx(uv); vec2 duv2 = dFdy(uv); // Solve the linear system vec3 dp2perp = cross(dp2, N); vec3 dp1perp = cross(N, dp1); vec3 T = dp2perp * duv1.x + dp1perp * duv2.x; vec3 B = dp2perp * duv1.y + dp1perp * duv2.y;

// Construct a scale-invariant frame float invmax = inversesqrt(max(dot(T,T), dot(B,B)); return mat3(T * invmax, B * invmax, N);}

vec3 pertub_normal(vec3 N, vec3 V, vec2 texcoord){ // assume N, the interpolated vertex normal and // V, the view vector(vertex to eye) vec3 map = texture2D(mapBump, texcoord).xyz;#ifdef WITH_NORMALMAP_UNSIGNED map = map * 255./127. – 128./127.; #endif#ifdef WITH_NORMALMAP_2CHANNEL map.z = sqrt(1. – dot(map.xy, map.xy)); #endif#ifdef WITH_NORMALMAP_GREEN_UP map.y = -map.y; #endif

mat3 TBN = cotangent_frame(N, -V, texcoord); return normalize(TBN * map);}

Contangent Frames

Page 16: Shaderx5 2.6normalmappingwithoutprecomputedtangents 130318 (1)

varying vec3 g_vertexnormal;varying vec3 g_viewvector; // camera pos – vertex posvarying vec2 g_texcoord;

void main(){ vec3 N = normalize(g_vertexnormal); vec3 V = normalize(g_viewvector);

#ifdef WITH_NORMALMAP N = perturb_normal(N, V, g_texcoord);#endif

// ...}

Contangent Frames (cont.)

Reference

(Followup) Normal mapping without precomputed tangentshttp://www.thetenthplanet.de/archives/1180

Covariance and contravariance of vectorshttp://en.wikipedia.org/wiki/Covariance_and_contravariance_of_vectors

Fast inverse square roothttp://en.wikipedia.org/wiki/Fast_inverse_square_root