//从小到大输入 private void RasterBottomTriangle(VertexOut v1, VertexOut v2, VertexOut v3, BaseShader shader) { VertexOut left = v1; VertexOut right = v2; VertexOut dest = v3; float weight = 0; VertexOut newLeft; VertexOut newRight; if (left.posProjective.x > right.posProjective.x) { VertexOut tmp = left; left = right; right = tmp; } int dy = (int)dest.posProjective.y - (int)left.posProjective.y + 1; for (int i = 0; i < dy; i++) { if (dy != 0) { weight = (float)i / dy; } newLeft = LerpVertexOut(left, dest, weight); newRight = LerpVertexOut(right, dest, weight); newLeft.posProjective.y = left.posProjective.y + i; newRight.posProjective.y = left.posProjective.y + i; ScanLinePerRow(newLeft, newRight, shader); } }
//按列逐行扫描 private void ScanLinePerRow(VertexOut left, VertexOut right, BaseShader shader) { VertexOut current; int length = (int)right.posProjective.x - (int)left.posProjective.x; if (length == 0) { return; } for (int i = 0; i <= length; i++) { float weight = (float)i / length; current = LerpVertexOut(left, right, weight); if (shader.ZTest == true) { if (current.posProjective.z >= 0.5f && current.posProjective.z > backBuffer.GetDepth((int)current.posProjective.x, (int)current.posProjective.y)) { continue; } } if (shader.ZWrite == true) { backBuffer.DrawDepth((int)current.posProjective.x, (int)current.posProjective.y, current.posProjective.z); } current.posProjective.x = left.posProjective.x + i; current.posProjective.y = left.posProjective.y; //透视纹理处理 shader.ProjectedMapRestore(current); //片段着色 backBuffer.DrawPixel((int)current.posProjective.x, (int)current.posProjective.y, shader.FragmentShader(current)); } }
public void Render() { ////测试画线函数------>>>>>> //VertexOut pA = new VertexOut(); //pA.posProjective = new Vector4D(100,0,0,1); //VertexOut pB = new VertexOut(); //pB.posProjective = new Vector4D(100, 100, 0, 1); //BresenhamLineRasterization(pA, pB); //return; ////测试画线函数<<<<<<<-------- /// Vector3D tmp = scene.camera.transform.GetPosition(); cameraPosition = new Vector3D(tmp.x, tmp.y, tmp.z); //cameraPosition.x = -cameraPosition.x; //cameraPosition.y = -cameraPosition.y; //cameraPosition.z = -cameraPosition.z; Vector3D up = new Vector3D(0, 1, 0); //up.x = -up.x; //up.y = -up.y; //up.z = -up.z; viewMatrix.SetLookAt(cameraPosition, new Vector3D(0, 0, 0), up); backBuffer.Clear(); //scene.camera for (int i = 0; i < scene.gameObjects.Count; i++) { GameObject3D gameObject = scene.gameObjects[i]; BaseShader shader = gameObject.meshRenderer.material.shader; shader.SetModelMatrix(gameObject.transform.ToMatrix()); shader.SetViewMatrix(viewMatrix); shader.SetEyePos(cameraPosition); shader.SetProjectMatrix(projectMatrix); shader.SetLight(scene.light); //图元装配 Mesh mesh = gameObject.meshRenderer.mesh; //Debug.LogError("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"); for (int j = 0; j < mesh.indices.Length; j += 3) { Vertex p1, p2, p3; p1 = mesh.vertices[mesh.indices[j]]; p2 = mesh.vertices[mesh.indices[j + 1]]; p3 = mesh.vertices[mesh.indices[j + 2]]; //顶点着色(遍历三角形) VertexOut vertexOut1, vertexOut2, vertexOut3; vertexOut1 = shader.VertexShader(p1); vertexOut2 = shader.VertexShader(p2); vertexOut3 = shader.VertexShader(p3); shader.ProjectedMap(vertexOut1); shader.ProjectedMap(vertexOut2); shader.ProjectedMap(vertexOut3); //背面裁剪 if (shader.backFaceCulling) { if (polygonMode != PolygonMode.Wire && !BackFaceCulling(vertexOut1.posWorld, vertexOut2.posWorld, vertexOut3.posWorld)) { continue; } } //透视处理 PerspectiveDivision(vertexOut1); PerspectiveDivision(vertexOut2); PerspectiveDivision(vertexOut3); //几何裁剪 //屏幕空间转换 vertexOut1.posProjective = Matrix4x4.MultiplyVector4D(viewPortMatrix, vertexOut1.posProjective); vertexOut2.posProjective = Matrix4x4.MultiplyVector4D(viewPortMatrix, vertexOut2.posProjective); vertexOut3.posProjective = Matrix4x4.MultiplyVector4D(viewPortMatrix, vertexOut3.posProjective); //Debug.LogError("vertexOut1.posProjective " + vertexOut1.posProjective.x // + " " + vertexOut1.posProjective.y + " " + vertexOut1.posProjective.z ); //Debug.LogError("vertexOut2.posProjective " + vertexOut2.posProjective.x // + " " + vertexOut2.posProjective.y + " " + vertexOut2.posProjective.z ); //Debug.LogError("vertexOut3.posProjective " + vertexOut3.posProjective.x // + " " + vertexOut3.posProjective.y + " " + vertexOut3.posProjective.z ); //Debug.LogError("-----------------"); //片段着色 if (polygonMode == PolygonMode.Wire) { //线框模式 BresenhamLineRasterization(vertexOut1, vertexOut2); BresenhamLineRasterization(vertexOut1, vertexOut3); BresenhamLineRasterization(vertexOut2, vertexOut3); } else { //三角形填充模式 EdgeWalkingFillRasterization(vertexOut1, vertexOut2, vertexOut3, shader); } } } }
private void EdgeWalkingFillRasterization(VertexOut v1, VertexOut v2, VertexOut v3, BaseShader shader) { //先把三个点按y从小到大排序 VertexOut[] targets = { v1, v2, v3 }; VertexOut tmp; if (targets[0].posProjective.y > targets[1].posProjective.y) { tmp = targets[0]; targets[0] = targets[1]; targets[1] = tmp; } if (targets[0].posProjective.y > targets[2].posProjective.y) { tmp = targets[0]; targets[0] = targets[2]; targets[2] = tmp; } if (targets[1].posProjective.y > targets[2].posProjective.y) { tmp = targets[1]; targets[1] = targets[2]; targets[2] = tmp; } if ((int)targets[0].posProjective.y == (int)targets[1].posProjective.y) { //下三角形 RasterBottomTriangle(targets[0], targets[1], targets[2], shader); } else if ((int)targets[1].posProjective.y == (int)targets[2].posProjective.y) { //上三角形 RasterTopTriangle(targets[0], targets[1], targets[2], shader); } else { //需要分割为上三角形下三角形 float weight = (targets[1].posProjective.y - targets[0].posProjective.y) / (targets[2].posProjective.y - targets[0].posProjective.y); VertexOut vertexOutNew = LerpVertexOut(targets[0], targets[2], weight); vertexOutNew.posProjective.y = targets[1].posProjective.y; RasterTopTriangle(targets[0], vertexOutNew, targets[1], shader); RasterBottomTriangle(vertexOutNew, targets[1], targets[2], shader); } }