/// <summary> /// 绘制三角形 /// </summary> /// <param name="p1"></param> /// <param name="p2"></param> /// <param name="p3"></param> /// <param name="mvp"></param> private void DrawTriangle(CVertex p1, CVertex p2, CVertex p3, CMatrix4x4 m, CMatrix4x4 v, CMatrix4x4 p) { //--------------------几何阶段--------------------------- //变换到齐次裁剪空 SetMVPTransform(m, v, p, p1); SetMVPTransform(m, v, p, p2); SetMVPTransform(m, v, p, p3); ////裁剪 if (Clip(p1) == false || Clip(p2) == false || Clip(p3) == false) { return; } //背面消隐 //if (BackFaceCulling(p1, p2, p3) == false) //{ // return; //} //变换到屏幕坐标 TransformToScreen(p1); VectorMatrixTestCase.showVector3(p1.point); TransformToScreen(p2); VectorMatrixTestCase.showVector3(p2.point); TransformToScreen(p3); VectorMatrixTestCase.showVector3(p3.point); //--------------------光栅化阶段--------------------------- //todo test //_frameBuff.SetPixel((int)p1.point.x, (int)p1.point.y, System.Drawing.Color.White); //_frameBuff.SetPixel((int)p2.point.x, (int)p2.point.y, System.Drawing.Color.White); //_frameBuff.SetPixel((int)p3.point.x, (int)p3.point.y, System.Drawing.Color.White); TriangleRasterization(p1, p2, p3); }
/// <summary> /// 进行mvp矩阵变换,将顶点变换到齐次裁剪空间 /// </summary> private void SetMVPTransform(CMatrix4x4 m, CMatrix4x4 v, CMatrix4x4 p, CVertex vertex) { vertex.point = vertex.point * m; VectorMatrixTestCase.showVector3(vertex.point); vertex.point = vertex.point * v; VectorMatrixTestCase.showVector3(vertex.point); vertex.point = vertex.point * p; VectorMatrixTestCase.showVector3(vertex.point); //得到齐次裁剪空间的点 v.point.w 中保存着原来的z(具体是z还是-z要看使用的投影矩阵,我们使用投影矩阵是让w中保存着z) //onePerZ 保存1/z,方便之后对1/z关于x’、y’插值得到1/z’ vertex.onePerZ = 1 / vertex.point.w; //校正的推论: s/z、t/z和x’、y’也是线性关系。而我们之前知道1/z和x’、y’是线性关系。则我们得出新的思路:对1/z关于x’、y’插值得到1/z’,然后对s/z、t/z关于x’、y’进行插值得到s’/z’、t’/z’,然后用s’/z’和t’/z’分别除以1/z’,就得到了插值s’和t’ //这里将需要插值的信息都乘以1/z 得到 s/z和t/z等,方便光栅化阶段进行插值 vertex.u *= vertex.onePerZ; vertex.v *= vertex.onePerZ; // vertex.color.r *= vertex.onePerZ; vertex.color.g *= vertex.onePerZ; vertex.color.b *= vertex.onePerZ; }