//从小到大输入 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); } }
public void ProjectedMapRestore(VertexOut vertexOut) { float w = 1.0f / vertexOut.oneDivZ; vertexOut.posWorld.MultiplyNum(w); vertexOut.texcoord.MultiplyNum(w); vertexOut.color.MultiplyNum(w); }
//处理透视纹理映射 public void ProjectedMap(VertexOut vertexOut) { //处理透视纹理映射 vertexOut.oneDivZ = 1.0f / vertexOut.posProjective.w; vertexOut.posWorld.MultiplyNum(vertexOut.oneDivZ); vertexOut.texcoord.MultiplyNum(vertexOut.oneDivZ); vertexOut.color.MultiplyNum(vertexOut.oneDivZ); }
private void PerspectiveDivision(VertexOut vertexOut) { vertexOut.posProjective.x /= vertexOut.posProjective.w; vertexOut.posProjective.y /= vertexOut.posProjective.w; vertexOut.posProjective.z /= vertexOut.posProjective.w; vertexOut.posProjective.w = 1; //[-1,1] to [0,1] vertexOut.posProjective.z = (vertexOut.posProjective.z + 1.0f) * 0.5f; }
//Bresenham画线法 用整数加减法代替浮点数加减法 private void BresenhamLineRasterization(VertexOut from, VertexOut to) { int x = (int)from.posProjective.x; int y = (int)from.posProjective.y; int toX = (int)to.posProjective.x; int toY = (int)to.posProjective.y; int deltax = toX - x; int deltay = toY - y; int stepx = 1; int stepy = 1; if (deltax < 0) { stepx = -1; } if (deltay < 0) { stepy = -1; } int eps = 0;//误差累计 deltax = Mathf.Abs(deltax); deltay = Mathf.Abs(deltay); if (deltax > deltay) { for (; x != toX; x += stepx) { eps += deltay; if ((eps << 1) >= deltax) { y += stepy; eps -= deltax; } backBuffer.DrawPixel(x, y, Color.White()); } } else { for (; y != toY; y += stepy) { eps += deltax; if ((eps << 1) >= deltay) { x += stepx; eps -= deltay; } backBuffer.DrawPixel(x, y, Color.White()); } } }
private VertexOut LerpVertexOut(VertexOut v1, VertexOut v2, float weight) { VertexOut vertexOut = new VertexOut(); vertexOut.posProjective = Vector4D.Lerp(v1.posProjective, v2.posProjective, weight); vertexOut.posWorld = Vector4D.Lerp(v1.posWorld, v2.posWorld, weight); vertexOut.color = Color.Lefp(v1.color, v2.color, weight); vertexOut.normal = Vector3D.Lerp(v1.normal, v2.normal, weight); vertexOut.texcoord = Vector2D.Lerp(v1.texcoord, v2.texcoord, weight); vertexOut.oneDivZ = (1 - weight) * v1.oneDivZ + weight * v2.oneDivZ; return(vertexOut); }
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); } }
public override VertexOut VertexShader(Vertex vertexIn) { VertexOut vertexOut = new VertexOut(); vertexOut.posWorld = Matrix4x4.MultiplyVector4D(modelMatrix, vertexIn.position); vertexOut.posProjective = Matrix4x4.MultiplyVector4D(viewMatrix, vertexOut.posWorld); vertexOut.posProjective = Matrix4x4.MultiplyVector4D(projectedMatrix, vertexOut.posProjective); vertexOut.color = vertexIn.color.Copy(); vertexOut.normal = vertexIn.normal.Copy(); vertexOut.normal = Matrix4x4.MultiplyVector4D(modelMatrixInverse, vertexOut.normal.ToVector4D()).ToVector3D(); vertexOut.texcoord = vertexIn.texcoord.Copy(); //vertexOut.oneDivZ = 1.0f / vertexOut.posProjective.w; //vertexOut.posWorld.MultiplyNum(vertexOut.oneDivZ); //vertexOut.texcoord.MultiplyNum(vertexOut.oneDivZ); //vertexOut.color.MultiplyNum(vertexOut.oneDivZ); return(vertexOut); }
public override Color FragmentShader(VertexOut vertexIn) { Color color = texture.Sample(vertexIn.texcoord.x, vertexIn.texcoord.y); //Color color = Color.Red(); if (light != null) { if (light.GetType() == typeof(DirectionalLight)) { color = color * ((DirectionalLight)light).Lighting( ambientColor, diffuseColor, specularColor, vertexIn.posWorld.ToVector3D(), vertexIn.normal, Vector3D.Minus(eyePos, vertexIn.posWorld)); color.a = 1; } } //return vertexIn.color; return(color); }
//按列逐行扫描 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 virtual Color FragmentShader(VertexOut vertexIn) { return(null); }