void DrawScanline(HScanline scanline) { HScreenDevice ScreenDevice = HScreenDevice.GetInstance(); List <byte> framebuffer = ScreenDevice.FrameBuff; List <float> zbuffer = ScreenDevice.DepthBuff; int x = (int)scanline.x; int y = (int)scanline.y; int scanlineWidth = (int)scanline.width; int ScreenWidth = ScreenDevice.ScreenWidth; int ScreenHeight = ScreenDevice.ScreenHeight; for (; scanlineWidth > 0; x++, scanlineWidth--) { if (x >= 0 && x < ScreenWidth) { float rhw = scanline.v.rhw; if (rhw >= zbuffer[x + y * ScreenWidth]) { float w = 1.0f / rhw; zbuffer[x + y * ScreenWidth] = rhw; float u = scanline.v.uv.u * w; float v = scanline.v.uv.v * w; v2f fragIn = new v2f(); fragIn.uv.u = u; fragIn.uv.v = v; int color = frag(fragIn); //片元着色器 byte r = (byte)0x0, g = (byte)0x0, b = (byte)0x0, a = (byte)0x0; MathHelper.GetRGBAFromInt(color, ref r, ref g, ref b, ref a); framebuffer[(x + y * ScreenWidth) * 4] = r; framebuffer[(x + y * ScreenWidth) * 4 + 1] = g; framebuffer[(x + y * ScreenWidth) * 4 + 2] = b; framebuffer[(x + y * ScreenWidth) * 4 + 3] = a; } } scanline.v = scanline.v.Add(scanline.step); if (x >= ScreenWidth) { break; } } }
// 主渲染函数 void DrawTrap(HTrapezoid trap) { //HScanline scanline; int j, top, bottom; top = (int)(trap.top + 0.5f); bottom = (int)(trap.bottom + 0.5f); for (j = top; j < bottom; j++) { if (j >= 0 && j < HScreenDevice.GetInstance().ScreenHeight) //todo //插值得到梯形的腰的两个点 { trap.EdgeInterp((float)j + 0.5f); //初始化扫描线 HScanline scanline = GetScanline(trap, j); //绘制扫描线 DrawScanline(scanline); } } }
// 根据左右两边的端点,初始化计算出扫描线的起点和步长 HScanline GetScanline(HTrapezoid trap, int y) { HScanline scanlineRet = new HScanline(); // 左右两点的 宽度 float width = trap.right.v.pos.x - trap.left.v.pos.x; // 起点X 坐标 scanlineRet.x = (int)(trap.left.v.pos.x + 0.5f); // 宽度 scanlineRet.width = (int)(trap.right.v.pos.x + 0.5f) - scanlineRet.x; // y坐标 scanlineRet.y = y; // 扫描起点 scanlineRet.v = trap.left.v.Copy(); // if (trap.left.v.pos.x >= trap.right.v.pos.x) { scanlineRet.width = 0; } //计算步伐 scanlineRet.step = trap.left.v.Step(trap.right.v, width); return(scanlineRet); }