public PSOutput FragShader(VSOutput v) { //invert uv if (shaderContext.invertTexture) { //v.texcoord = new Vector2(1 - v.texcoord.X, 1 - v.texcoord.Y); v.texcoord = new Vector2(v.texcoord.X, 1 - v.texcoord.Y); //v.texcoord = new Vector2(1 - v.texcoord.X, v.texcoord.Y); } PSOutput OUT = new PSOutput(); Vector4 col = v.color; if ((shaderContext.shadeMode == ShadeMode.Lighting || shaderContext.shadeMode == ShadeMode.NDotL) && shaderContext.light != null) { Vector3 normalWorld = v.normalWorld; normalWorld = Vector3.Normalize(normalWorld); Vector3 lightDir = shaderContext.light.lightDirForShader; //Lambert Lighting float NDotL = Vector3.Dot(normalWorld, lightDir); NDotL = Utils.Clamp(NDotL, 0, 1); if (shaderContext.shadeMode == ShadeMode.Lighting && texture != null) { Vector4 tex = texture.Tex2D(v.texcoord, shaderContext.textureFilterMode); col = tex * (NDotL * shaderContext.light.lightColor + shaderContext.ambient); } else { col = new Vector4(NDotL, NDotL, NDotL, 1f); } } else if (shaderContext.shadeMode == ShadeMode.Texture && texture != null) { col = texture.Tex2D(v.texcoord, shaderContext.textureFilterMode); } //col = new Vector4(v.texcoord.X, v.texcoord.Y, 0, 1 ); OUT.color = col; return(OUT); }
public void BarycentricRasterizeTriangle(VSOutput v0, VSOutput v1, VSOutput v2) { int width = context.frameSize.Width; int height = context.frameSize.Height; Vector2 xy0 = new Vector2(v0.posScreen.X, v0.posScreen.Y); Vector2 xy1 = new Vector2(v1.posScreen.X, v1.posScreen.Y); Vector2 xy2 = new Vector2(v2.posScreen.X, v2.posScreen.Y); float z0 = v0.posScreen.Z; float z1 = v1.posScreen.Z; float z2 = v2.posScreen.Z; //求包围盒 float xmin = Math.Min(Math.Min(xy0.X, xy1.X), xy2.X); float xmax = Math.Max(Math.Max(xy0.X, xy1.X), xy2.X); float ymin = Math.Min(Math.Min(xy0.Y, xy1.Y), xy2.Y); float ymax = Math.Max(Math.Max(xy0.Y, xy1.Y), xy2.Y); //像素坐标包围盒 int x0 = Utils.Clamp((int)xmin, 0, width - 1); int y0 = Utils.Clamp((int)ymin, 0, height - 1); int x1 = Utils.Clamp((int)xmax, 0, width - 1); int y1 = Utils.Clamp((int)ymax, 0, height - 1); for (int y = y0; y <= y1; ++y) { for (int x = x0; x <= x1; ++x) { //加0.5取像素的中间位置的坐标 Vector2 pixel = new Vector2(x + 0.5f, y + 0.5f); Vector3 w = BarycentricCoordinates(pixel, xy0, xy1, xy2); float w0 = w.X; float w1 = w.Y; float w2 = w.Z; if (!(w0 >= 0 && w1 >= 0 && w2 >= 0)) { //像素点不在三角形内 continue; } context.statics.fragmentCount += 1; //深度测试 float depth = w0 * z0 + w1 * z1 + w2 * z2; if (context.depthBuffer[x, y] < depth) { continue; } Color col; if (context.drawMode == DrawMode.Depth) { Vector4 depthColor = new Vector4(depth, depth, depth, 1); col = Utils.VectorToColor(depthColor); } else { //正常渲染 //插值UV等顶点属性 float fInvW = w0 * v0.position.W + w1 * v1.position.W + w2 * v2.position.W; //由于position.W是1/W = 1/-Z_Eye float Z_Eye = 1f / fInvW; Vector2 uv = w0 * v0.texcoord + w1 * v1.texcoord + w2 * v2.texcoord; uv *= Z_Eye; Vector4 color = w0 * v0.color + w1 * v1.color + w2 * v2.color; color *= Z_Eye; Vector3 normalWorld = w0 * v0.normalWorld + w1 * v1.normalWorld + w2 * v2.normalWorld; if (shader != null) { VSOutput fragment = new VSOutput(); //v.position = fragment.normalWorld = normalWorld; fragment.texcoord = uv; fragment.color = color; PSOutput OUT = shader.FragShader(fragment); if (OUT.isDiscard) { continue; } col = Utils.VectorToColor(OUT.color); } else { col = Utils.VectorToColor(color); } } context.depthBuffer[x, y] = depth; DrawPixel(x, y, col); } } }