/// <summary> /// 画一个点 /// </summary> /// <param name="point"></param> /// <param name="c"></param> public void DrawPoint(Vector4 point, Color3 c) { if (point.X >= 0 && point.Y >= 0 && point.X <= Width && point.Y <= Height) { if (point.X == Width) { point.X = point.X - 1; } if (point.Y == Height) { point.Y = point.Y - 1; } Putpixel((int)point.X, (int)point.Y, point.Z, c); } }
/// <summary> /// 绘画某个位置的像素 /// </summary> /// <param name="x"></param> /// <param name="y"></param> /// <param name="z"></param> /// <param name="color"></param> public void Putpixel(int x, int y, float z, Color3 color) { int index = (x + y * Width); if (m_DepthBuffer[index] < z) { return; } m_DepthBuffer[index] = z; unsafe { byte *ptr = (byte *)(this.m_BmData.Scan0); byte *row = ptr + (y * this.m_BmData.Stride); row[x * 3] = color.B; row[x * 3 + 1] = color.G; row[x * 3 + 2] = color.R; } }
/// <summary> /// 实现了“基础光照模型”,在世界空间进行顶点光照处理 /// </summary> /// <param name="position"></param> /// <param name="normal"></param> /// <param name="light"></param> /// <returns></returns> public Color3 GetLightColor(Vector4 position, Vector4 normal, Light light, Vector4 cameraPosition) { // 环境光 Color3 ambient = light.Color * m_Material.AmbientStregth; //自发光 Color3 emissive = m_Material.Emssive; // 漫反射 Vector4 nor = normal * m_Transform; Vector4 lightdir = (light.Position - position).Normalize(); float diff = Math.Max(Vector4.Dot(normal.Normalize(), lightdir), 0); Color3 diffuse = m_Material.Diffuse * diff; Vector4 viewDir = (cameraPosition - position).Normalize(); Vector4 h = (viewDir + lightdir).Normalize(); float specular = (float)System.Math.Pow(Clamp(Vector4.Dot(h, normal)), m_Material.Shininess); Color3 specularColor = m_Material.Specular * specular * light.Color;//镜面高光 return(ambient + diffuse + specularColor + emissive); }
/// <summary> /// 画一条直线 /// </summary> /// <param name="point0"></param> /// <param name="point1"></param> /// <param name="scene"></param> /// <param name="v1"></param> /// <param name="v2"></param> public void DrawLine(Vector4 point0, Vector4 point1, Scene scene, Vertex v1, Vertex v2) { int x0 = (int)point0.X; int y0 = (int)point0.Y; int x1 = (int)point1.X; int y1 = (int)point1.Y; int dx = x1 - x0; int dy = y1 - y0; int steps = Math.Max(Math.Abs(dx), Math.Abs(dy)); if (steps == 0) { return; } float offsetX = (float)dx / (float)steps; float offsetY = (float)dy / (float)steps; float x = x0; float y = y0; Color3 vColor = new Color3(128, 128, 128); for (int i = 1; i <= steps; i++) { float dt = (float)(i) / (float)steps; vColor = MathUntily.Lerp(v1.Color, v2.Color, dt); float z = MathUntily.Lerp(point0.Z, point1.Z, dt); if (float.IsNaN(z)) { return; } DrawPoint(new Vector4((int)x, (int)y, z, 0), vColor); x += offsetX; y += offsetY; } }
/// <summary> /// 求交点, 返回的pos是裁剪空间下坐标 /// </summary> /// <param name="v1"></param> /// <param name="v2"></param> /// <param name="face"></param> /// <param name="wMin"></param> /// <param name="wMax"></param> /// <returns></returns> Vertex Intersect(Vertex v1, Vertex v2, FaceTypes face, Vector4 wMin, Vector4 wMax) { Vertex vertex = new Vertex(); float k1 = 0, k2 = 0, k3 = 0, k4 = 0, k5 = 0, k6 = 0; Vector4 p1 = v1.ClipPosition; Vector4 p2 = v2.ClipPosition; if (p1.X != p2.X) { k1 = (wMin.X - p1.X) / (p2.X - p1.X); k2 = (wMax.X - p1.X) / (p2.X - p1.X); } else { k1 = k2 = 1; } if (p1.Y != p2.Y) { k3 = (wMin.Y - p1.Y) / (p2.Y - p1.Y); k4 = (wMax.Y - p1.Y) / (p2.Y - p1.Y); } else { k3 = k4 = 1; } if (p1.Z != p2.Z) { k5 = (wMin.Z - p1.Z) / (p2.Z - p1.Z); k6 = (wMax.Z - p1.Z) / (p2.Z - p1.Z); } else { k5 = k6 = 1; } Vector4 clipPos = new Vector4(); Vector4 pos = new Vector4(); Color3 col = new Color3(0, 0, 0); Vector4 normal = new Vector4(); Vector2 uv = new Vector2(); switch (face) { case FaceTypes.LEFT: clipPos.X = wMin.X; clipPos.Y = p1.Y + (p2.Y - p1.Y) * k1; clipPos.Z = p1.Z + (p2.Z - p1.Z) * k1; clipPos.W = p1.W + (p2.W - p1.W) * k1; col = MathUntily.Lerp(v1.Color, v2.Color, k1); normal = MathUntily.Lerp(v1.Normal, v2.Normal, k1); pos = MathUntily.Lerp(v1.Position, v2.Position, k1); uv = MathUntily.Lerp(v1.UV, v2.UV, k1); break; case FaceTypes.RIGHT: clipPos.X = wMax.X; clipPos.Y = p1.Y + (p2.Y - p1.Y) * k2; clipPos.Z = p1.Z + (p2.Z - p1.Z) * k2; clipPos.W = p1.W + (p2.W - p1.W) * k2; col = MathUntily.Lerp(v1.Color, v2.Color, k2); normal = MathUntily.Lerp(v1.Normal, v2.Normal, k2); pos = MathUntily.Lerp(v1.Position, v2.Position, k2); uv = MathUntily.Lerp(v1.UV, v2.UV, k2); break; case FaceTypes.BUTTOM: clipPos.Y = wMin.Y; clipPos.X = p1.X + (p2.X - p1.X) * k3; clipPos.Z = p1.Z + (p2.Z - p1.Z) * k3; clipPos.W = p1.W + (p2.W - p1.W) * k3; col = MathUntily.Lerp(v1.Color, v2.Color, k3); normal = MathUntily.Lerp(v1.Normal, v2.Normal, k3); pos = MathUntily.Lerp(v1.Position, v2.Position, k3); uv = MathUntily.Lerp(v1.UV, v2.UV, k3); break; case FaceTypes.TOP: clipPos.Y = wMax.Y; clipPos.X = p1.X + (p2.X - p1.X) * k4; clipPos.Z = p1.Z + (p2.Z - p1.Z) * k4; clipPos.W = p1.W + (p2.W - p1.W) * k4; col = MathUntily.Lerp(v1.Color, v2.Color, k4); normal = MathUntily.Lerp(v1.Normal, v2.Normal, k4); pos = MathUntily.Lerp(v1.Position, v2.Position, k4); uv = MathUntily.Lerp(v1.UV, v2.UV, k4); break; case FaceTypes.NEAR: clipPos.Z = wMin.Z; clipPos.X = p1.X + (p2.X - p1.X) * k5; clipPos.Y = p1.Y + (p2.Y - p1.Y) * k5; clipPos.W = p1.W + (p2.W - p1.W) * k5; col = MathUntily.Lerp(v1.Color, v2.Color, k5); normal = MathUntily.Lerp(v1.Normal, v2.Normal, k5); pos = MathUntily.Lerp(v1.Position, v2.Position, k5); uv = MathUntily.Lerp(v1.UV, v2.UV, k5); break; case FaceTypes.FAR: clipPos.Z = wMax.Z; clipPos.X = p1.X + (p2.X - p1.X) * k6; clipPos.Y = p1.Y + (p2.Y - p1.Y) * k6; clipPos.W = p1.W + (p2.W - p1.W) * k6; col = MathUntily.Lerp(v1.Color, v2.Color, k6); normal = MathUntily.Lerp(v1.Normal, v2.Normal, k6); pos = MathUntily.Lerp(v1.Position, v2.Position, k6); uv = MathUntily.Lerp(v1.UV, v2.UV, k6); break; } vertex.Position = pos; vertex.ClipPosition = clipPos; vertex.ScreenPosition = this.m_Device.ViewPort(clipPos); vertex.Normal = normal; vertex.UV = uv; vertex.Color = col; return(vertex); }