void ProcessScanLine_GS(ScanLineData data, Vertex A, Vertex B, Vertex C, Vertex D, Color color, bool blin) { var pa = A.Position; var pb = B.Position; var pc = C.Position; var pd = D.Position; var gradient1 = pa.y != pb.y ? (data.currentY - pa.y) / (pb.y - pa.y) : 1; var gradient2 = pc.y != pd.y ? (data.currentY - pc.y) / (pd.y - pc.y) : 1; int sx = (int)Interpolate(pa.x, pb.x, gradient1); int ex = (int)Interpolate(pc.x, pd.x, gradient2); double z1 = Interpolate(pa.z, pb.z, gradient1); double z2 = Interpolate(pc.z, pd.z, gradient2); var sNoL = Interpolate(data.NoLa, data.NoLb, gradient1); var eNoL = Interpolate(data.NoLc, data.NoLd, gradient2); double sNoH = 0, eNoH = 0, sRoV = 0, eRoV = 0; if (blin) { sNoH = Interpolate(data.NoHa, data.NoHb, gradient1); eNoH = Interpolate(data.NoHc, data.NoHd, gradient2); } else { sRoV = Interpolate(data.RoVa, data.RoVb, gradient1); eRoV = Interpolate(data.RoVc, data.RoVd, gradient2); } for (var x = sx; x < ex; x++) { double gradient = (x - sx) / (double)(ex - sx); var z = Interpolate(z1, z2, gradient); var NoL = Interpolate(sNoL, eNoL, gradient); byte r = 0, g = 0, b = 0; if (blin) { var NoH = Interpolate(sNoH, eNoH, gradient); r = Limit(kd * color.R * NoL + ks * color.R * NoH); g = Limit(kd * color.R * NoL + ks * color.R * NoH); b = Limit(kd * color.R * NoL + ks * color.R * NoH); } else { var RoV = Interpolate(sRoV, eRoV, gradient); r = Limit(kd * color.R * NoL + ks * color.R * RoV); g = Limit(kd * color.R * NoL + ks * color.R * RoV); b = Limit(kd * color.R * NoL + ks * color.R * RoV); } var shadedColor = Color.FromArgb(color.A, r, g, b); DrawPoint(new Vector3(x, data.currentY, z), shadedColor); } }
void ProcessScanLine_FS(ScanLineData data, Vector3 A, Vector3 B, Vector3 C, Vector3 D, Color color, bool blin) { var gradient1 = A.y != B.y ? (data.currentY - A.y) / (B.y - A.y) : 1; var gradient2 = C.y != D.y ? (data.currentY - C.y) / (D.y - C.y) : 1; int sx = (int)Interpolate(A.x, B.x, gradient1); int ex = (int)Interpolate(C.x, D.x, gradient2); double z1 = Interpolate(A.z, B.z, gradient1); double z2 = Interpolate(C.z, D.z, gradient2); for (var x = sx; x < ex; x++) { double gradient = (x - sx) / (double)(ex - sx); var z = Interpolate(z1, z2, gradient); var NoL = data.NoLa; var RoV = data.RoVa; var NoH = data.NoHa; byte r = 0, g = 0, b = 0; if (blin) { r = Limit(kd * color.R * NoL + ks * color.R * NoH); g = Limit(kd * color.R * NoL + ks * color.R * NoH); b = Limit(kd * color.R * NoL + ks * color.R * NoH); } else { r = Limit(kd * color.R * NoL + ks * color.R * RoV); g = Limit(kd * color.R * NoL + ks * color.R * RoV); b = Limit(kd * color.R * NoL + ks * color.R * RoV); } var shadedColor = Color.FromArgb(color.A, r, g, b); DrawPoint(new Vector3(x, data.currentY, z), shadedColor); } }
public void DrawTriangle_GS(Vertex v1, Vertex v2, Vertex v3, Color color, double Time, Vector3 viewerPosition, bool blin = false) { if (v1.Position.y > v2.Position.y) { Swap(ref v1, ref v2); } if (v2.Position.y > v3.Position.y) { Swap(ref v2, ref v3); } if (v1.Position.y > v2.Position.y) { Swap(ref v1, ref v2); } var p1 = v1.Position; var p2 = v2.Position; var p3 = v3.Position; Vector3 lightPos = LP; double NoL1 = Compute_NoL(v1.WorldPosition, v1.Normal, lightPos); double NoL2 = Compute_NoL(v2.WorldPosition, v2.Normal, lightPos); double NoL3 = Compute_NoL(v3.WorldPosition, v3.Normal, lightPos); double RoV1 = 0, RoV2 = 0, RoV3 = 0; double NoH1 = 0, NoH2 = 0, NoH3 = 0; if (blin) { var H1 = Compute_H(v1.WorldPosition, viewerPosition, lightPos); var H2 = Compute_H(v2.WorldPosition, viewerPosition, lightPos); var H3 = Compute_H(v3.WorldPosition, viewerPosition, lightPos); H1.Normalize(); H2.Normalize(); H3.Normalize(); var Nnorm1 = v1.Normal; var Nnorm2 = v2.Normal; var Nnorm3 = v3.Normal; Nnorm1.Normalize(); Nnorm2.Normalize(); Nnorm3.Normalize(); NoH1 = Vector3.Dot(Nnorm1, H1); NoH2 = Vector3.Dot(Nnorm2, H2); NoH3 = Vector3.Dot(Nnorm3, H3); NoH1 = Math.Pow(NoH1, alpha); NoH2 = Math.Pow(NoH2, alpha); NoH3 = Math.Pow(NoH3, alpha); } else { var R1 = Compute_R(v1.WorldPosition, v1.Normal, lightPos); var R2 = Compute_R(v2.WorldPosition, v2.Normal, lightPos); var R3 = Compute_R(v3.WorldPosition, v3.Normal, lightPos); R1.Normalize(); R2.Normalize(); R3.Normalize(); var V1 = viewerPosition - v1.WorldPosition; var V2 = viewerPosition - v2.WorldPosition; var V3 = viewerPosition - v3.WorldPosition; V1.Normalize(); V2.Normalize(); V3.Normalize(); RoV1 = OverZero(Vector3.Dot(R1, V1)); RoV2 = OverZero(Vector3.Dot(R2, V2)); RoV3 = OverZero(Vector3.Dot(R3, V3)); RoV1 = Math.Pow(RoV1, alpha); RoV2 = Math.Pow(RoV2, alpha); RoV3 = Math.Pow(RoV3, alpha); } var data = new ScanLineData { }; double dP1P2, dP1P3; if (p2.y - p1.y > 0) { dP1P2 = (p2.x - p1.x) / (p2.y - p1.y); } else { dP1P2 = 0; } if (p3.y - p1.y > 0) { dP1P3 = (p3.x - p1.x) / (p3.y - p1.y); } else { dP1P3 = 0; } if (dP1P2 > dP1P3) { for (var y = (int)p1.y; y <= (int)p3.y; y++) { data.currentY = y; if (y < p2.y) { data.NoLa = NoL1; data.NoLb = NoL3; data.NoLc = NoL1; data.NoLd = NoL2; if (blin) { data.NoHa = NoH1; data.NoHb = NoH3; data.NoHc = NoH1; data.NoHd = NoH2; } else { data.RoVa = RoV1; data.RoVb = RoV3; data.RoVc = RoV1; data.RoVd = RoV2; } ProcessScanLine_GS(data, v1, v3, v1, v2, color, blin); } else { data.NoLa = NoL1; data.NoLb = NoL3; data.NoLc = NoL2; data.NoLd = NoL3; if (blin) { data.NoHa = NoH1; data.NoHb = NoH3; data.NoHc = NoH2; data.NoHd = NoH3; } else { data.RoVa = RoV1; data.RoVb = RoV3; data.RoVc = RoV2; data.RoVd = RoV3; } ProcessScanLine_GS(data, v1, v3, v2, v3, color, blin); } } } else { for (var y = (int)p1.y; y <= (int)p3.y; y++) { data.currentY = y; if (y < p2.y) { data.NoLa = NoL1; data.NoLb = NoL2; data.NoLc = NoL1; data.NoLd = NoL3; if (blin) { data.NoHa = NoH1; data.NoHb = NoH2; data.NoHc = NoH1; data.NoHd = NoH3; } else { data.RoVa = RoV1; data.RoVb = RoV2; data.RoVc = RoV1; data.RoVd = RoV3; } ProcessScanLine_GS(data, v1, v2, v1, v3, color, blin); } else { data.NoLa = NoL2; data.NoLb = NoL3; data.NoLc = NoL1; data.NoLd = NoL3; if (blin) { data.NoHa = NoH1; data.NoHb = NoH2; data.NoHc = NoH1; data.NoHd = NoH3; } else { data.RoVa = RoV1; data.RoVb = RoV2; data.RoVc = RoV1; data.RoVd = RoV3; } ProcessScanLine_GS(data, v2, v3, v1, v3, color, blin); } } } }
public void DrawTriangle_FS(Vertex v1, Vertex v2, Vertex v3, Color color, double Time, Vector3 viewerPosition, bool blin = false) { if (v1.Position.y > v2.Position.y) { Swap(ref v1, ref v2); } if (v2.Position.y > v3.Position.y) { Swap(ref v2, ref v3); } if (v1.Position.y > v2.Position.y) { Swap(ref v1, ref v2); } var p1 = v1.Position; var p2 = v2.Position; var p3 = v3.Position; Vector3 vnFace = (v1.Normal + v2.Normal + v3.Normal) / 3; Vector3 centerPoint = (v1.WorldPosition + v2.WorldPosition + v3.WorldPosition) / 3; Vector3 lightPos = LP; double NoL = Compute_NoL(centerPoint, vnFace, lightPos); double NoH = 0, RoV = 0; if (blin) { var H = Compute_H(v1.WorldPosition, viewerPosition, lightPos); H.Normalize(); var Nnorm1 = v1.Normal; Nnorm1.Normalize(); NoH = Vector3.Dot(Nnorm1, H); NoH = Math.Pow(NoH, alpha); } else { var R = Compute_R(centerPoint, vnFace, lightPos); R.Normalize(); var V = viewerPosition - centerPoint; V.Normalize(); RoV = OverZero(Vector3.Dot(R, V)); RoV = Math.Pow(RoV, alpha); } var data = new ScanLineData { NoLa = NoL, RoVa = RoV, NoHa = NoH }; double dP1P2, dP1P3; if (p2.y - p1.y > 0) { dP1P2 = (p2.x - p1.x) / (p2.y - p1.y); } else { dP1P2 = 0; } if (p3.y - p1.y > 0) { dP1P3 = (p3.x - p1.x) / (p3.y - p1.y); } else { dP1P3 = 0; } if (dP1P2 > dP1P3) { for (var y = (int)p1.y; y <= (int)p3.y; y++) { data.currentY = y; if (y < p2.y) { ProcessScanLine_FS(data, p1, p3, p1, p2, color, blin); } else { ProcessScanLine_FS(data, p1, p3, p2, p3, color, blin); } } } else { for (var y = (int)p1.y; y <= (int)p3.y; y++) { data.currentY = y; if (y < p2.y) { ProcessScanLine_FS(data, p1, p2, p1, p3, color, blin); } else { ProcessScanLine_FS(data, p2, p3, p1, p3, color, blin); } } } }