// const float M_PI = 3.141592653589793; vec4 SRGBtoLINEAR(vec4 srgbIn) { vec3 linOut = pow(srgbIn.xyz,vec3(2.2)); return vec4(linOut, srgbIn.a); } // http://www.thetenthplanet.de/archives/1180 // modified to fix handedness of the resulting cotangent frame mat3 cotangentFrame( 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) ) ); // calculate handedness of the resulting cotangent frame float w = (dot(cross(N, T), B) < 0.0) ? -1.0 : 1.0; // adjust tangent if needed T = T * w; return mat3( T * invmax, B * invmax, N ); } vec3 perturbNormal(vec3 n, vec3 v, vec3 normalSample, vec2 uv) { vec3 map = normalize( 2.0 * normalSample - vec3(1.0) ); mat3 TBN = cotangentFrame(n, v, uv); return normalize(TBN * map); }