参考:https://www.bilibili.com/video/BV1Kr4y1Q7kq/?p=8
原理:
SetPixel(hdc, x, y, RGB(e * 255, e * 255, e * 255));
SetPixel(hdc, x, y + 1, RGB((1 - e) * 255, (1 - e) * 255, (1 - e) * 255));
完成代码:
// 08-第一个八分象限直线的Wu反走样算法
// 参考 https://www.bilibili.com/video/BV1Kr4y1Q7kq/?p=8
#ifndef UNICODE
#define UNICODE
#endif
#include <math.h>
#include <Windows.h>
#include <stdio.h>
#include <wchar.h>
#include <WinBase.h>
#define PI 3.1415926 // PI
#define ROUND(d) int(d+0.5) // 四舍五入
#define WINDOW_TEXT L"08-第一个八分象限直线的Wu反走样算法"
// 二维点
struct Point2
{
Point2():x(0), y(0){}
Point2(double x, double y):x(x), y(y){}
double x;
double y;
};
// Wu反走样
void WuAntiLine(HDC hdc, Point2 p1, Point2 p2)
{
int dx = p2.x - p1.x;
int dy = p2.y - p1.y;
double k = double(dy) / dx;
double e = 0;
for (int x = p1.x, y = p1.y; x < p2.x; x++)
{
SetPixel(hdc, x, y, RGB(e * 255, e * 255, e * 255));
SetPixel(hdc, x, y + 1, RGB((1 - e) * 255, (1 - e) * 255, (1 - e) * 255));
e += k;
if (e >= 1.0)
{
y++;
e--;
}
}
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
HDC hdc;
RECT rc;
switch (uMsg)
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_PAINT:
{
hdc = BeginPaint(hwnd, &ps);
GetClientRect(hwnd, &rc);
SetMapMode(hdc, MM_ANISOTROPIC);
SetWindowExtEx(hdc, rc.right, rc.bottom, NULL);
SetViewportExtEx(hdc, rc.right, -rc.bottom, NULL);
SetViewportOrgEx(hdc, rc.right / 2, rc.bottom / 2, NULL);
Point2 p1(-300, -100);
Point2 p2(300, 100);
// Wu反走样绘制线
WuAntiLine(hdc, p1, p2);
EndPaint(hwnd, &ps);
}
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow)
{
// Register the window class.
const wchar_t CLASS_NAME[] = L"CAG";
WNDCLASS wc = { };
wc.style = CS_HREDRAW | CS_VREDRAW; // 重新绘制整个工作区
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
RegisterClass(&wc);
HWND hwnd = CreateWindowEx(
0, // Optional window styles.
CLASS_NAME, // Window class
WINDOW_TEXT, // Window text
WS_OVERLAPPEDWINDOW, // Window style
// Size and position
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, // Parent window
NULL, // Menu
hInstance, // Instance handle
NULL // Additional application data
);
if (hwnd == NULL)
{
return 0;
}
ShowWindow(hwnd, nCmdShow);
MSG msg = { };
while (GetMessage(&msg, NULL, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}