diff --git a/main.cpp b/main.cpp index fa9bd7e9..8ce61dda 100644 --- a/main.cpp +++ b/main.cpp @@ -18,13 +18,16 @@ Vec3f up(0,1,0); struct Shader : public IShader { mat<2,3,float> varying_uv; // triangle uv coordinates, written by the vertex shader, read by the fragment shader + mat<4,3,float> varying_tri; // triangle coordinates (clip coordinates), written by VS, read by FS mat<3,3,float> varying_nrm; // normal per vertex to be interpolated by FS + mat<3,3,float> ndc_tri; // triangle in normalized device coordinates virtual Vec4f vertex(int iface, int nthvert) { varying_uv.set_col(nthvert, model->uv(iface, nthvert)); varying_nrm.set_col(nthvert, proj<3>((Projection*ModelView).invert_transpose()*embed<4>(model->normal(iface, nthvert), 0.f))); Vec4f gl_Vertex = Projection*ModelView*embed<4>(model->vert(iface, nthvert)); varying_tri.set_col(nthvert, gl_Vertex); + ndc_tri.set_col(nthvert, proj<3>(gl_Vertex/gl_Vertex[3])); return gl_Vertex; } @@ -32,8 +35,26 @@ struct Shader : public IShader { Vec3f bn = (varying_nrm*bar).normalize(); Vec2f uv = varying_uv*bar; - float diff = std::max(0.f, bn*light_dir); + mat<3,3,float> A; + A[0] = ndc_tri.col(1) - ndc_tri.col(0); + A[1] = ndc_tri.col(2) - ndc_tri.col(0); + A[2] = bn; + + mat<3,3,float> AI = A.invert(); + + Vec3f i = AI * Vec3f(varying_uv[0][1] - varying_uv[0][0], varying_uv[0][2] - varying_uv[0][0], 0); + Vec3f j = AI * Vec3f(varying_uv[1][1] - varying_uv[1][0], varying_uv[1][2] - varying_uv[1][0], 0); + + mat<3,3,float> B; + B.set_col(0, i.normalize()); + B.set_col(1, j.normalize()); + B.set_col(2, bn); + + Vec3f n = (B*model->normal(uv)).normalize(); + + float diff = std::max(0.f, n*light_dir); color = model->diffuse(uv)*diff; + return false; } };