OpenGL接口的基本实现1[转]
目录
Windows API 参考:Windows 编程之路
绘制点
- Raster.h
#pragma once #include "CELLMath.hpp" namespace CELL { class Raster { public: Rgba* _buffer; int _width; int _height; public: Raster(int w, int h, void* buffer); ~Raster(void); void clear(); void drawPoint(int x, int y, Rgba color, int ptSize); public: inline void setPixel(unsigned x, unsigned y, Rgba color) { if (x >= _width || y >= _height) { return; } _buffer[y * _width + x] = color; } }; }
- Raster.cpp
#include "Raster.h" namespace CELL { Raster::Raster(int w, int h, void* buffer) { _width = w; _height = h; _buffer = (Rgba*)buffer; } Raster::~Raster(void) { } void Raster::clear() { memset(_buffer, 0, _width * _height * sizeof(Rgba)); } void Raster::drawPoint(int x, int y, Rgba color, int ptSize) { switch (ptSize) { case 1: setPixel(x, y, color); break; case 2: setPixel(x + 0, y + 0, color); setPixel(x + 1, y + 0, color); setPixel(x + 0, y + 1, color); setPixel(x + 1, y + 1, color); break; } } }
- main.cpp
#include <windows.h> #include <tchar.h> #include "Raster.h" LRESULT CALLBACK windowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_SIZE: break; case WM_CLOSE: case WM_DESTROY: PostQuitMessage(0); break; default: break; } return DefWindowProc(hWnd, msg, wParam, lParam); } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) { // 1 注册窗口类 ::WNDCLASSEXA winClass; winClass.lpszClassName = "Raster"; winClass.cbSize = sizeof(::WNDCLASSEX); winClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC | CS_DBLCLKS; winClass.lpfnWndProc = windowProc; winClass.hInstance = hInstance; winClass.hIcon = 0; winClass.hIconSm = 0; winClass.hCursor = LoadCursor(NULL, IDC_ARROW); winClass.hbrBackground = (HBRUSH)(BLACK_BRUSH); winClass.lpszMenuName = NULL; winClass.cbClsExtra = 0; winClass.cbWndExtra = 0; RegisterClassExA(&winClass); // 2 创建窗口 HWND hWnd = CreateWindowExA( NULL, "Raster", "Raster", WS_POPUPWINDOW, 200, 200, 256, 256, 0, 0, hInstance, 0 ); UpdateWindow(hWnd); ShowWindow(hWnd, SW_SHOW); //获取窗口大小 RECT rt = { 0 }; GetClientRect(hWnd, &rt); int width = rt.right - rt.left; int height = rt.bottom - rt.top; void* buffer = 0; HDC hDC = GetDC(hWnd); HDC hMem = ::CreateCompatibleDC(hDC); BITMAPINFO bmpInfor; bmpInfor.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bmpInfor.bmiHeader.biWidth = width; bmpInfor.bmiHeader.biHeight = height; bmpInfor.bmiHeader.biPlanes = 1; bmpInfor.bmiHeader.biBitCount = 32; bmpInfor.bmiHeader.biCompression = BI_RGB; bmpInfor.bmiHeader.biSizeImage = 0; bmpInfor.bmiHeader.biXPelsPerMeter = 0; bmpInfor.bmiHeader.biYPelsPerMeter = 0; bmpInfor.bmiHeader.biClrUsed = 0; bmpInfor.bmiHeader.biClrImportant = 0; HBITMAP hBmp = CreateDIBSection(hDC, &bmpInfor, DIB_RGB_COLORS, (void**)&buffer, 0, 0); SelectObject(hMem, hBmp); CELL::Raster raster(width, height, buffer); MSG msg = { 0 }; while (true) { if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } if (msg.message == WM_DESTROY || msg.message == WM_CLOSE || msg.message == WM_QUIT) { break; } raster.clear(); for (int i = 0; i < 100; ++i) { raster.drawPoint(rand() % 256, rand() % 256, CELL::Rgba(255, 0, 0), 2); } memcpy(buffer, raster._buffer, raster._width * raster._height * sizeof(CELL::Rgba)); BitBlt(hDC, 0, 0, width, height, hMem, 0, 0, SRCCOPY); } return 0; }
绘制直线
void drawLine(float2 pt1, float2 pt2, Rgba color) { float xOffset = pt1.x - pt2.x; float yOffset = pt1.y - pt2.y; if (xOffset == 0 && yOffset == 0) { setPixel(pt1.x, pt1.y, color); } if (fabs(xOffset) > fabs(yOffset)) { float slope = yOffset / xOffset; float xMin; float xMax; if (pt1.x < pt2.x) { xMin = pt1.x; xMax = pt2.x; } else { xMin = pt2.x; xMax = pt1.x; } for (float x = xMin; x <= xMax; x += 1.0f) { float y = pt1.y + (x - pt1.x) * slope; setPixel(x, y, color); } } else { float slope = xOffset / yOffset; float yMin; float yMax; if (pt1.y < pt2.y) { yMin = pt1.y; yMax = pt2.y; } else { yMin = pt2.y; yMax = pt1.y; } for (float y = pt1.y; y <= pt2.y; y += 1.0f) { float x = pt1.x + (y - pt1.y) * slope; setPixel(pt2.x, y, color); } } }
- 调用:
raster.drawLine(CELL::float2(-11, 111), CELL::float2(666, 222), CELL::Rgba(255, 0, 0));
绘制颜色渐变直线
void Raster::drawLine( float2 pt1,float2 pt2,Rgba color1,Rgba color2 ) { float xOffset = pt1.x - pt2.x; float yOffset = pt1.y - pt2.y; if (xOffset == 0 && yOffset == 0) { setPixel(pt1.x,pt1.y,color1); } if (fabs(xOffset) > fabs(yOffset)) { float slope = yOffset / xOffset; float xMin; float xMax; if (pt1.x < pt2.x) { xMin = pt1.x; xMax = pt2.x; } else { xMin = pt2.x; xMax = pt1.x; } float lenth = xMax - xMin; for (float x = xMin; x <= xMax ; x += 1.0f) { float y = pt1.y + (x - pt1.x) * slope; float scaler = (x - xMin)/lenth; Rgba color = colorLerp(color1,color2,scaler); setPixel(x,y,color); } } else { float slope = xOffset / yOffset; float yMin; float yMax; if (pt1.y < pt2.y) { yMin = pt1.y; yMax = pt2.y; } else { yMin = pt2.y; yMax = pt1.y; } float lenth = yMax - yMin; for (float y = pt1.y; y <= pt2.y ; y += 1.0f) { float x = pt1.x + (y - pt1.y) * slope; float scaler = (y - yMin)/lenth; Rgba color = colorLerp(color1,color2,scaler); setPixel(pt2.x,y,color); } } }
- 调用:
raster.drawLine(CELL::float2(1,100),CELL::float2(200,33),CELL::Rgba(255,0,0),CELL::Rgba(0,255,0));
绘制线封装
enum DRAWMODE { DM_POINTS = 0, DM_LINES = 1, DM_LINE_LOOP = 2, DM_LINE_STRIP = 3, }; void drawArrays(DRAWMODE mode, const float2* points, int count) { switch (mode) { case DM_POINTS: { for (int i = 0; i < count; ++i) { drawPoints(points[i], _color); } } break; case DM_LINES: { count = count / 2 * 2; for (int i = 0; i < count - 1; ++i) { drawLine(points[i], points[i + 1], _color, _color); } } break; case DM_LINE_LOOP: { drawLine(points[0], points[1], _color, _color); for (int i = 2; i < count; ++i) { drawLine(points[i - 1], points[i], _color, _color); } drawLine(points[0], points[count - 1], _color, _color); } break; case DM_LINE_STRIP: { drawLine(points[0], points[1], _color, _color); for (int i = 2; i < count; ++i) { drawLine(points[i - 1], points[i], _color, _color); } } break; default: break; } }
- 调用:
CELL::float2 arPoints[] = { CELL::float2(11,34), CELL::float2(33,66), CELL::float2(1,100), CELL::float2(22,88), CELL::float2(100,1), }; raster.drawArrays(CELL::DM_LINE_STRIP, arPoints, sizeof(arPoints) / sizeof(arPoints[0])); //绘制直线 CELL::float2 arPoints1[] = { CELL::float2(0,0), CELL::float2(133,166), }; raster.drawArrays(CELL::DM_LINES, arPoints1, 2); //绘制圆 CELL::float2 center(100, 100); float radius = 80; CELL::float2 arCircle[360]; for (int i = 0; i < 360; ++i) { float rad = DEG2RAD(i); arCircle[i].x = radius * cos(rad) + center.x; arCircle[i].y = radius * sin(rad) + center.y; } raster.drawArrays(CELL::DM_LINE_STRIP, arCircle, sizeof(arCircle) / sizeof(arCircle[0]));
贝塞尔曲线绘制
CELL::float2 points[] = { CELL::float2(50,50), CELL::float2(20,360), CELL::float2(89,10), CELL::float2(159,100), }; CELL::float2 prev[2]; for (float t = 0; t < 1.0f; t += 0.01f) { float x = points[0].x * pow(1 - t, 3) + 3 * points[1].x * t * pow(1 - t, 2) + 3 * points[2].x * t*t * (1 - t) + points[3].x * t * t * t; float y = points[0].y * pow(1 - t, 3) + 3 * points[1].y * t * pow(1 - t, 2) + 3 * points[2].y * t*t * (1 - t) + points[3].y * t * t * t; if (t == 0) { prev[0] = CELL::float2(x, y); } else { prev[1] = CELL::float2(x, y); raster.drawArrays(CELL::DM_LINES, prev, 2); prev[0] = prev[1]; } }