void DrawEntity(Entity entity) { Mesh mesh = entity.meshFilter.mesh; Transform objectTransform = entity.transform; Texture2D mainTex = entity.mainTex; for (int i = 0; i < mesh.triangles.Length; i += 3) { int a_index = mesh.triangles[i]; int b_index = mesh.triangles[i + 1]; int c_index = mesh.triangles[i + 2]; TriangleAttribute <Color> colors = new TriangleAttribute <Color>(Color.red, Color.green, Color.blue); TriangleAttribute <Vector2> uvs = new TriangleAttribute <Vector2>(mesh.uv[a_index], mesh.uv[b_index], mesh.uv[c_index]); Vector4 a = V4Point(mesh.vertices[a_index]); Vector4 b = V4Point(mesh.vertices[b_index]); Vector4 c = V4Point(mesh.vertices[c_index]); m_Transform m_objectTransform = new m_Transform(); m_objectTransform.CopyFromTransform(objectTransform); a = m_objectTransform.TransformPoint(a); b = m_objectTransform.TransformPoint(b); c = m_objectTransform.TransformPoint(c); TriangleAttribute <Vector3> pos_worlds = new TriangleAttribute <Vector3>(a, b, c); TriangleAttribute <Vector3> normals = new TriangleAttribute <Vector3>( m_objectTransform.TransformDirection(mesh.normals[a_index]), m_objectTransform.TransformDirection(mesh.normals[b_index]), m_objectTransform.TransformDirection(mesh.normals[c_index])); m_Transform cam_t = new m_Transform(); cam_t.CopyFromTransform(cam.transform); a = cam_t.InverseTransformPoint(a); b = cam_t.InverseTransformPoint(b); c = cam_t.InverseTransformPoint(c); Matrix4x4 p = GetProjectionMatrix(cam); Matrix4x4 negetive = Matrix4x4.identity; negetive.m22 = -1; Matrix4x4 total = p * negetive; a = ClipSpaceToScreenSpace(total * V4Point(a), pixelWidth, pixelHeight); b = ClipSpaceToScreenSpace(total * V4Point(b), pixelWidth, pixelHeight); c = ClipSpaceToScreenSpace(total * V4Point(c), pixelWidth, pixelHeight); a.z = a.w; b.z = b.w; c.z = c.w; Triangle3D triangle = new Triangle3D(a, b, c); //z值为摄像机空间z坐标 DrawTriangle(colorBuffer, triangle, colors, uvs, pos_worlds, normals, mainTex); } }
public void DrawTriangle(Texture2D colorBuffer, Triangle3D t, TriangleAttribute <Color> colors, TriangleAttribute <Vector2> uvs, TriangleAttribute <Vector3> pos_worlds, TriangleAttribute <Vector3> normals, Texture2D mainTex) { Vector2 min = Vector2.Min(Vector2.Min(t.a, t.b), t.c); Vector2 max = Vector2.Max(Vector2.Max(t.a, t.b), t.c); Vector2Int min_int = ClampInScreenSpace(pixelWidth, pixelHeight, Vector2Int.FloorToInt(min)); Vector2Int max_int = ClampInScreenSpace(pixelWidth, pixelHeight, Vector2Int.FloorToInt(max)); t.a.z = 1 / t.a.z; t.b.z = 1 / t.b.z; t.c.z = 1 / t.c.z; colors.a *= t.a.z; colors.b *= t.b.z; colors.c *= t.c.z; uvs.a *= t.a.z; uvs.b *= t.b.z; uvs.c *= t.c.z; pos_worlds.a *= t.a.z; pos_worlds.b *= t.b.z; pos_worlds.c *= t.c.z; normals.a *= t.a.z; normals.b *= t.b.z; normals.c *= t.c.z; for (int y = min_int.y; y <= max_int.y; y++) { for (int x = min_int.x; x <= max_int.x; x++) { Vector2 p = new Vector2(x + 0.5f, y + 0.5f); float ab = EdgeTest(t.a, t.b, p); if (ab < 0) { continue; } float bc = EdgeTest(t.b, t.c, p); if (bc < 0) { continue; } float ca = EdgeTest(t.c, t.a, p); if (ca < 0) { continue; } float area = EdgeTest(t.a, t.b, t.c); float w_a = bc / area; float w_b = ca / area; float w_c = ab / area; float z = 1 / (w_a * t.a.z + w_b * t.b.z + w_c * t.c.z); if (!DepthTest(x, y, z / cam.farClipPlane)) { continue; } Color color = z * (colors.a * w_a + colors.b * w_b + colors.c * w_c); Vector2 uv = z * (uvs.a * w_a + uvs.b * w_b + uvs.c * w_c); Vector3 pos_world = z * (pos_worlds.a * w_a + pos_worlds.b * w_b + pos_worlds.c * w_c); Vector3 normal = z * (normals.a * w_a + normals.b * w_b + normals.c * w_c); Color col; if (chekerBoard) { col = FragmentShader_ChckerBorad(uv, pos_world, normal, mainTex); } else { col = FragmentShader_BlinnPhong(uv, pos_world, normal, mainTex); } colorBuffer.SetPixel(x, y, col); } } }