private void RenderHorizontalLine(IDisplayer displayer, int x1, int x2, int y, double z1, double z2, Color color, List <Light> lights, Color gourandIntensity1, Color gourandIntensity2, Vector normal1, Vector normal2, Vector cameraPos, Vector world1, Vector world2) { double z = 0; if (x1 > x2) { int tmp = x1; x1 = x2; x2 = tmp; double tmp2 = z1; z1 = z2; z2 = tmp2; Color tmp3 = gourandIntensity1; gourandIntensity1 = gourandIntensity2; gourandIntensity2 = tmp3; Vector nTmp = null; if (normal1 != null) { nTmp = normal1.Clone(); normal1 = normal2.Clone(); normal2 = nTmp; } Vector wTmp = null; if (world1 != null) { wTmp = world1.Clone(); world1 = world2.Clone(); world2 = wTmp; } } for (int x = x1; x <= x2; ++x) { Color usedColor = new Color(); if (displayer.GetShading() == Shading.Gourand) { usedColor = InterpolateColorGourandShading(x2, x1, x, gourandIntensity2, gourandIntensity1); } else if (displayer.GetShading() == Shading.Phong) { Vector normal = InterpolateNormalPhongShading(x2, x1, x, normal2, normal1); Vector world = InterpolateWorldPhongShading(x2, x1, x, world2, world1); usedColor = ComputeColorPhongModel(color, lights, world, cameraPos, normal, displayer.IsFog()); } else { usedColor = color; } double q = x2 == x1 ? 0 : (x - x1) / (x2 - x1); z = InterpolateZ(z1, z2, q); displayer.Display(x, y, z, usedColor); // TODO: consider changing to primitive types instead of passing Vector } }
private void FillBottomTriangle(IDisplayer displayer, int x0, int y0, double z0, Color c0, Vector n0, Vector w0, int x1, int y1, double z1, Color c1, Vector n1, Vector w1, int x2, int y2, double z2, Color c2, Vector n2, Vector w2, Color color, List <Light> lights, Vector cameraPos) { double d1 = (double)(x1 - x0) / (double)(y1 - y0 + 1); double d2 = (double)(x2 - x0) / (double)(y2 - y0 + 1); double xa = x0; double xb = x0; for (int sc = y0; sc <= y1; ++sc) { Color leftInsensity = new Color(); Color rightIntensity = new Color(); Vector leftNormal = null, rightNormal = null, leftWorld = null, rightWorld = null; if (displayer.GetShading() == Shading.Gourand) { leftInsensity = InterpolateColorGourandShading(y1, y0, sc, c1, c0); rightIntensity = InterpolateColorGourandShading(y2, y0, sc, c2, c0); } else if (displayer.GetShading() == Shading.Phong) { leftNormal = InterpolateNormalPhongShading(y1, y0, sc, n1, n0); rightNormal = InterpolateNormalPhongShading(y2, y0, sc, n2, n0); leftWorld = InterpolateWorldPhongShading(y1, y0, sc, w1, w0); rightWorld = InterpolateWorldPhongShading(y2, y0, sc, w2, w0); } xa += d1; xb += d2; RenderHorizontalLine(displayer, (int)xa, (int)xb, sc, InterpolateZ(z0, z1, (double)(sc - y0) / (double)(y1 - y0)), InterpolateZ(z0, z2, (double)(sc - y0) / (double)(y1 - y0)), color, lights, leftInsensity, rightIntensity, leftNormal, rightNormal, cameraPos, leftWorld, rightWorld); } }
private void RenderFillingScanLine(IDisplayer displayer, Color color, List <Light> lights, Vector cameraPos) // TODO: Fix missing Gourand cases (if, else if) { List <Vertex> vertices = new List <Vertex>() { v1, v2, v3 }; vertices.Sort(CompareByY); int x0 = (int)vertices[0].GetScreenPosition().x; int y0 = (int)vertices[0].GetScreenPosition().y; int x1 = (int)vertices[1].GetScreenPosition().x; int y1 = (int)vertices[1].GetScreenPosition().y; int x2 = (int)vertices[2].GetScreenPosition().x; int y2 = (int)vertices[2].GetScreenPosition().y; double z0 = vertices[0].GetScreenPosition().z; double z1 = vertices[1].GetScreenPosition().z; double z2 = vertices[2].GetScreenPosition().z; if (displayer.GetShading() == Shading.Gourand) { PrepareGourandVertexIntensities(color, lights, cameraPos, vertices, displayer.IsFog()); } else if (displayer.GetShading() == Shading.Flat) { color = ComputeColorPhongModel(color, lights, GetWorldMiddle(), cameraPos, normalVector, displayer.IsFog()); } Color c0 = vertices[0].GetScreenPosition().GetColor(); Color c1 = vertices[1].GetScreenPosition().GetColor(); Color c2 = vertices[2].GetScreenPosition().GetColor(); Vector n0 = null, n1 = null, n2 = null; Vector w0 = null, w1 = null, w2 = null; if (displayer.GetShading() == Shading.Phong) { n0 = vertices[0].GetNormalVector(); n1 = vertices[1].GetNormalVector(); n2 = vertices[2].GetNormalVector(); w0 = vertices[0].GetWorldPosition(); w1 = vertices[1].GetWorldPosition(); w2 = vertices[2].GetWorldPosition(); } if (y1 == y2) { FillBottomTriangle(displayer, x0, y0, z0, c0, n0, w0, x1, y1, z1, c1, n1, w1, x2, y2, z2, c2, n2, w2, color, lights, cameraPos); } else if (y0 == y1) { FillTopTriangle(displayer, x0, y0, z0, c0, n0, w0, x1, y1, z1, c1, n1, w1, x2, y2, z2, c2, n2, w2, color, lights, cameraPos); } else { int x3 = x0 + (int)(((double)(y1 - y0) / (double)(y2 - y0)) * (x2 - x0)); int y3 = y1; double z3 = InterpolateZ(z0, z2, (double)(y1 - y0) / (double)(y2 - y0)); Color c3 = new Color(); Vector n3 = null, w3 = null; if (displayer.GetShading() == Shading.Gourand) { c3 = InterpolateColorGourandShading(y2, y0, y1, c2, c0); } else if (displayer.GetShading() == Shading.Phong) { n3 = InterpolateNormalPhongShading(y2, y0, y1, n2, n0); w3 = InterpolateWorldPhongShading(y2, y0, y1, w2, w0); } FillBottomTriangle(displayer, x0, y0, z0, c0, n0, w0, x1, y1, z1, c1, n1, w1, x3, y3, z3, c3, n3, w3, color, lights, cameraPos); FillTopTriangle(displayer, x1, y1, z1, c1, n1, w1, x3, y3, z3, c3, n3, w3, x2, y2, z2, c2, n2, w2, color, lights, cameraPos); } }