csdn学院图形学视频教程个人笔记

05直线的颜色运算-绘制彩色直线

//CCanvas.h
#pragma once

#include "gameMath.h"
#include <string.h>

namespace GT
{
	struct RGBA
	{
		btye m_b;
		btye m_g;
		btye m_r;
		btye m_a;

		RGBA(btye _r = 255,
			btye _g = 255,
			btye _b = 255,
			btye _a = 255)
		{
			m_r = _r;
			m_g = _g;
			m_b = _b;
			m_a = _a;
		}

	};
	
	class Point
	{
	public:
		int m_x;
		int m_y;
		RGBA m_color;

		Point(int _x, int _y, RGBA _color)
		{
			m_x = _x;
			m_y = _y;
			m_color = _color;
		}
		~Point()
		{

		}

	};

	class CCanvas
	{
	private:
		int		m_width;
		int		m_height;
		
		RGBA*	m_buffer;

	public:
		CCanvas(int _width, int _height, void* _buffer)
		{
			if (_width <= 0 || _height <= 0)
			{
				m_width = -1;
				m_height = -1;
				m_buffer = nullptr;
			}

			m_width = _width;
			m_height = _height;
			m_buffer = (RGBA*)_buffer;
		}

		~CCanvas()
		{
			
		}

		//清屏
		void clear()
		{
			if (m_buffer != nullptr)
			{
				memset(m_buffer, 0, sizeof(RGBA) * m_width * m_height);
			}
		}
		//画点操作

		void drawPoint(int x, int y, RGBA _color)
		{
			if (x < 0 || x >= m_width || y < 0 || y >= m_height)
			{
				return;
			}

			m_buffer[y * m_width + x] = _color;
		}

		void drawLine(intV2 pt1, intV2 pt2, RGBA _color);
		inline RGBA colorLerp(RGBA _color1, RGBA _color2, float _scale)
		{
			RGBA _color;
			_color.m_r = _color1.m_r + (float)(_color2.m_r - _color1.m_r) * _scale;
			_color.m_g = _color1.m_g + (float)(_color2.m_g - _color1.m_g) * _scale;
			_color.m_b = _color1.m_b + (float)(_color2.m_b - _color1.m_b) * _scale;
			_color.m_a = _color1.m_a + (float)(_color2.m_a - _color1.m_a) * _scale;
			return _color;
		}

		//画线操作 渐变色
		void drawLine(Point pt1, Point pt2);
	};
}


/CCanvas.cpp
#include "CCanvas.h"
#include <math.h>
namespace GT
{
	void CCanvas::drawLine(Point pt1, Point pt2)
	{
		int disY = abs(pt2.m_y - pt1.m_y);
		int disX = abs(pt2.m_x - pt1.m_x);

		int xNow = pt1.m_x;
		int yNow = pt1.m_y;

		int stepX = 0;
		int stepY = 0;

		if (pt1.m_x < pt2.m_x)
			stepX = 1;
		else
			stepX = -1;

		if (pt1.m_y < pt2.m_y)
			stepY = 1;
		else
			stepY = -1;

		//对比xy偏移量,决定步进的方向选取x or y
		int sumStep = disX;
		bool useXstep = true;

		if (disX < disY)
		{
			sumStep = disY;
			useXstep = false;
			SWAP_INT(disX, disY);
		}

		//初始化P值
		int p = 2 * disY - disX;

		for (int i = 0; i < sumStep; ++i)
		{
			RGBA _color;
			float _scale = 0;
			if (useXstep)
			{
				_scale = (float)(xNow - pt1.m_x) / (float)(pt2.m_x - pt1.m_x);
			}
			else
			{
				_scale = (float)(yNow - pt1.m_y) / (float)(pt2.m_y - pt1.m_y);
			}
			_color = colorLerp(pt1.m_color, pt2.m_color, _scale);
			drawPoint(xNow, yNow, _color);

			if (p >= 0)
			{
				if (useXstep)
				{
					yNow += stepY;
				 }
				else
				{
					xNow += stepX;
				}
				p = p - 2 * disX;
				
			}


			//步进主坐标
			if (useXstep)
			{
				xNow += stepX;
			}
			else
			{
				yNow += stepY;
			}

			p = p + 2 * disY;
		}

	};

	void CCanvas::drawLine(intV2 pt1, intV2 pt2, RGBA _color)
	{
		//偏移值
		int disY = abs(pt2.y - pt1.y);
		int disX = abs(pt2.x - pt1.x);

		//目前坐标
		int xNow = pt1.x;
		int yNow = pt1.y;

		//步进值
		int stepX = 0;
		int stepY = 0;

		//判断两个方向步进的正负
		if (pt1.x < pt2.x)
			stepX = 1;
		else
			stepX = -1;

		if (pt1.y < pt2.y)
			stepY = 1;
		else
			stepY = -1;


		//对比xy偏移量, 决定步进的方向选取x or y

		int sumStep = disX;
		bool useXStep = true;

		if (disX < disY)
		{
			sumStep = disY;
			useXStep = false;
			SWAP_INT(disX, disY);
		}

		//初始化P值
		int p = 2 * disY - disX;

		for (int i = 0; i < sumStep; ++i)
		{
			drawPoint(xNow, yNow, _color);

			if (p >= 0)
			{
				if (useXStep)
				{
					yNow += stepY;
				}
				else
				{
					xNow += stepX;
				}

				p = p - 2 * disX;
				
			}

			//步进主坐标
			if (useXStep)
			{
				xNow += stepX;
			}
			else
			{
				yNow += stepY;
			}

			p = p + 2 * disY;
		}

	}
}


//gameMath.h

#pragma once
#define PI 3.14151926
#define MIN(a,b) ((a)<(b)?(a):(b))
#define MAX(a,b) ((a)>(b)?(a):(b))
#define DEG2RAD(theta) (0.01745329251994329 * (theta))
template<typename T>
void swap(T& a, T& b)
{
	T temp = a;
	a = b;
	b = temp;
}
#define SWAP_INT(a, b) swap<int>(a, b);
namespace GT
{
	template<typename T>
	struct tVec2
	{
		T x;
		T y;

		tVec2(T _x, T _y)
		{
			x = _x;
			y = _y;
		}
		tVec2()
		{
			x = -1;
			y = -1;
		}

	};

	

	typedef tVec2<int>	intV2;
	typedef tVec2<float> floatV2;

	typedef unsigned int uint;
	typedef unsigned char btye;
}

//main.cpp
#include <Windows.h>
#include <tchar.h>
#include "CCanvas.h"
#include <math.h>
//窗口类名
const TCHAR szWindowClass[] = L"class";
//窗口标题
const TCHAR szWindowName[] = L"冒险岛v0.1";
//窗口句柄
HWND hWnd;
//窗口宽度
int wWidth = 800;
//窗口高度
int wHeight = 600;
//DC
HDC hDC;
//内存DC
HDC hMemDC;
GT::CCanvas* _canvas = NULL;

//消息处理回调函数
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
//渲染函数
void Render(HDC hdc);
int WINAPI wWinMain(HINSTANCE hInstance,
	HINSTANCE hPrevInstance,
	LPWSTR lpCmdLine,
	int nCmdShow)
{
	//注册窗口类
	WNDCLASSEXW wcex;
	wcex.cbSize = sizeof(WNDCLASSEXW);
	//窗口水平或者垂直方向改变重画
	wcex.style			= CS_HREDRAW | CS_VREDRAW;
	//回调函数
	wcex.lpfnWndProc	= WndProc;
	//类和窗口扩展内存 默认写0
	wcex.cbClsExtra		= 0;
	wcex.cbWndExtra		= 0;
	//实例句柄 从wWinMain参数的hInstance
	wcex.hInstance		= hInstance;
	//窗口图标
	wcex.hIcon			= LoadIcon(nullptr, IDI_APPLICATION);
	//窗口鼠标指针样式
	wcex.hCursor		= LoadCursor(nullptr, IDC_ARROW);
	//窗口背景
	wcex.hbrBackground	= (HBRUSH)GetStockObject(WHITE_BRUSH);
	//窗口菜单
	wcex.lpszMenuName	= nullptr;
	//窗口类名
	wcex.lpszClassName	= szWindowClass;
	//窗口小图标
	wcex.hIconSm		= LoadIcon(nullptr, IDI_APPLICATION);

	if (!RegisterClassEx(&wcex)) return -1;
	//创建窗口
	hWnd = CreateWindowEx(0, szWindowClass, szWindowName,
		WS_POPUP, 0, 0, wWidth, wHeight,
		nullptr, nullptr, hInstance, nullptr);

	if (!hWnd) return -2;

	//显示并更新窗口

	//缓冲
	void* buffer = 0;

	hDC = GetDC(hWnd);
	hMemDC = CreateCompatibleDC(hDC);

	BITMAPINFO bmpInfo;
	bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
	bmpInfo.bmiHeader.biWidth = wWidth;
	bmpInfo.bmiHeader.biHeight = wHeight;
	bmpInfo.bmiHeader.biPlanes = 1;
	bmpInfo.bmiHeader.biBitCount = 32;
	bmpInfo.bmiHeader.biCompression = BI_RGB;
	bmpInfo.bmiHeader.biSizeImage = 0;
	bmpInfo.bmiHeader.biXPelsPerMeter = 0;
	bmpInfo.bmiHeader.biYPelsPerMeter = 0;
	bmpInfo.bmiHeader.biClrUsed = 0;
	bmpInfo.bmiHeader.biClrImportant = 0;

	//创建buffer的内存
	HBITMAP hBmp = CreateDIBSection(hDC, &bmpInfo, DIB_RGB_COLORS,
		(void**)&buffer, 0, 0);
	//选入对象
	SelectObject(hMemDC, hBmp);

	memset(buffer, 0, wWidth * wHeight * 4);

	_canvas = new GT::CCanvas(wWidth, wHeight, buffer);

	ShowWindow(hWnd, nCmdShow);
	UpdateWindow(hWnd);

	

	MSG msg = { 0 };

	//消息循环
	while (GetMessage(&msg, nullptr, 0, 0))
	{
		
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		
		
		//Render();
		
	}
	ReleaseDC(hWnd, hDC);
	return (int)msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	PAINTSTRUCT ps;
	switch (msg)
	{
	case WM_PAINT:
		{
		HDC hdc = BeginPaint(hwnd, &ps);
		Render(hdc);
		EndPaint(hwnd, &ps);
		}
		return 0;
	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;
	}
	return ::DefWindowProc(hwnd, msg, wParam, lParam);
}

void Render(HDC hdc)
{

	_canvas->clear();
	
	GT::Point pt1(200, 200, GT::RGBA(255,0,0));
	
	GT::intV2 pt1_(100, 100);
	//_canvas->drawLine(GT::intV2(100,100),GT::intV2(300,300), GT::RGBA(16,225,200));
	
	float dis = 200;
	/*
	for (float i = 0; i < 360; i += 10)
	{
		float radian = DEG2RAD(i);
		int x = dis * sin(radian) + pt1_.x;
		int y = dis * cos(radian) + pt1_.y;

		GT::intV2 pt2(x, y);

		_canvas->drawLine(pt1_, pt2, GT::RGBA(120, 120, 90));
	}
	*/
	for (float i = 0; i < 360; i += 20)
	{
		

		float radian = DEG2RAD(i);

		int x = dis * sin(radian) + pt1.m_x;
		int y = dis * cos(radian) + pt1.m_y;
		GT::Point pt2(x, y, GT::RGBA(120, 200,0));

		_canvas->drawLine(pt1, pt2);
	}

	BitBlt(hDC, 0, 0, wWidth, wHeight, hMemDC, 0, 0,
		SRCCOPY);
}

效果图在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值