Okay, so I derived a nice equation for bi-quartic interpolation and took partial Deriviatives of it (Fx and Fy)
then according to this
http://mathworld.wolfram.com/NormalVector.html I got a normal vector (had to invert it for purpose of normal map)
you could modify this so it works with other interpolation function,
HOWEVER IT MUST BE AN EVEN-ORDER POLYNOMIAL, i.e. CANNOT USE BILINEAR,CUBIC,QUINTIC INTERPOLATION
This is because you have to have N+1 points to define ONLY ONE polynomial of N-Degree that passes through them (interpolates)
Because you want to get gradient, and therefore Normal at the same point as the middle of your sampling pattern, you need M points of either side to make the polynomial
M+1+M gives 1+2M which will always be odd, and an odd N+1 number of points requires an Even Order polynomial
THIS IS WHY IRRLICHT BUILT-IN NORMAL MAP GENERATION DOES NOT WORK PROPERLY!!!!
(Look at why the gradient of a y=|x| graph is underterminate at x=0 )
So here is the shader, I will soon translate to C++ which will take in one file and spit out a displacement map (RGBA) in .png format
Code: Select all
/**
THIS CODE IS UNDER LGPL v3
Work by Mateusz 'devsh' Kielan
**/
uniform sampler2D tex;
uniform float heightScale; // relative to where 1.0 is the size of one pixel
uniform texSz;
void main()
{
//round down to nearest texel
vec2 UV_disc = floor(gl_TexCoord[0].xy*texSz)/texSz+vec2(0.5)/texSz;
float Z[5][5];
float Dx,Dy;
for (int i=-2; i<=2; i++)
{
Z[i+2][2] = texture2D(tex,UV_disc+vec2(i,0)/texSz).r*heightScale;
}
for (int i=-2; i<=2; i++)
{
Z[2][i+2] = texture2D(tex,UV_disc+vec2(0,i)/texSz).r*heightScale;
}
/// MUL((k-x)/(k-j),k=-N toinc N,k!=j)
float PjmX[5];
PjmX[0] = Z[0][2]/12.0; // j=-2
PjmX[1] = -2.0*Z[1][2]/3.0; // j=-1
PjmX[3] = 2.0*Z[3][2]/3.0; // j=1
PjmX[4] = -Z[4][2]/12.0; // j=2
Dx = PjmX[0]+PjmX[1]+PjmX[3]+PjmX[4];
PjmX[0] = Z[2][0]/12.0; // m=-2
PjmX[1] = -2.0*Z[2][1]/3.0; // m=-1
PjmX[3] = 2.0*Z[2][3]/3.0; // m=1
PjmX[4] = -Z[2][4]/12.0; // m=2
Dy = PjmX[0]+PjmX[1]+PjmX[3]+PjmX[4];
gl_FragColor.rgba = vec4(normalize(-vec3(Dx,Dy,-1.0))*0.5+vec3(0.5),Z[2][2]);
// higher precision storage
//gl_FragColor.rgba = vec4(normalize(-vec3(Dx,Dy,-1.0))*vec3(0.5,0.5,1.0)+vec3(0.5,0.5,0.0),Z[2][2]);
}
Next I'll make a normal map generator which derives the gradients from the sinc()/Lanczos interpolation