C++模拟OpenGL库——图形学状态机接口封装(一):用状态模式重构部分代码及接口定义

目录

什么是状态机?

基于状态机模式进行重构

Canvas.h源码


什么是状态机?

回顾之前两部分内容,我们做了:

  • 绘制点
  • 绘制线(Brensenham)
  • 绘制三角形(拆分法)
  • 图片操作(stb_image.h)
  • 纹理贴图
  • 效果处理

我们思考OpenGL是基于什么思想来做的,或者说什么样的设计模式?

答:状态机。那么什么是状态机?

状态机:

  • 记录状态参数
  • 更改状态参数
  • 使用状态参数做事

白话解释:你给我什么参数,我就做什么事。给我true我就去做,false就不去做。

为什么用状态机?

  • 图形学的程序结构特殊性,每个阶段关心的事情不一样
  • 渲染管线的设置后处理的方便性
  • 接口的整洁性

基于状态机模式进行重构

基于以上考虑和分析,我们对现有代码进行小小的重构:

canvas.h:

添加数据元类型,绘图模式,数据元素类:

	enum DATA_TYPE {
		GT_FLOAT=0,
		GT_INT=1
	};

	enum DRAW_MODE {
		GT_LINE=0,
		GL_TRIANGLE=1
	};

	struct DataElement {
		int			m_size;
		DATA_TYPE	m_type;
		int			m_stride;//每次取点的步长
		byte*		m_data;//数据空间指针

		DataElement() {
			m_size = -1;
			m_type = GT_FLOAT;
			m_stride = 0;
			m_data = nullptr;
		}
	};

 将之前Canvan类中的一些变量,抽象出来,到一个Statement类中:

随后添加部分状态机接口:

//===========状态机接口===============
void gtVertexPointer(int _size, DATA_TYPE _type, int _stride, byte* _data);
void gtColorPointer(int _size, DATA_TYPE _type, int _stride, byte* _data);
void gtTexCoordPointer(int _size, DATA_TYPE _type, int _stride, byte* _data);
void gtDrawArray(DRAW_MODE _mode,int _first,int _count);//从first的点,画count个点
	void Canvas::gtVertexPointer(int _size, DATA_TYPE _type, int _stride, byte* _data)
	{
		m_state.m_vertexData.m_size = _size;
		m_state.m_vertexData.m_type = _type;
		m_state.m_vertexData.m_stride = _stride;
		m_state.m_vertexData.m_data = _data;
	}

	void Canvas::gtColorPointer(int _size, DATA_TYPE _type, int _stride, byte* _data)
	{
		m_state.m_colorData.m_size = _size;
		m_state.m_colorData.m_type = _type;
		m_state.m_colorData.m_stride = _stride;
		m_state.m_colorData.m_data = _data;
	}

	void Canvas::gtTexCoordPointer(int _size, DATA_TYPE _type, int _stride, byte* _data)
	{
		m_state.m_texCoordData.m_size = _size;
		m_state.m_texCoordData.m_type = _type;
		m_state.m_texCoordData.m_stride = _stride;
		m_state.m_texCoordData.m_data = _data;
	}

	void Canvas::gtDrawArray(DRAW_MODE _mode, int _first, int _count)
	{

	}

Canvas.h源码

为了方便查看,这里贴出Canvas.h的整体源码,也是对之前的一个总结梳理:

#pragma once
#include "GTMATH.hpp"
#include <string.h>
#include <vector>
#include "Image.h"

namespace GT {
	//点类
	class Point {
	public:
		int m_x;
		int m_y;
		RGBA m_color;
		floatV2 m_uv;

		Point(int _x = 0, int _y = 0, RGBA _color = RGBA(0, 0, 0, 0), floatV2 _uv = floatV2(0.0, 0.0)) {
			m_x = _x, m_y = _y, m_color = _color, m_uv = _uv;
		}

		~Point() {}
	};

	enum DATA_TYPE {
		GT_FLOAT=0,
		GT_INT=1
	};

	enum DRAW_MODE {
		GT_LINE=0,
		GL_TRIANGLE=1
	};

	struct DataElement {
		int			m_size;
		DATA_TYPE	m_type;
		int			m_stride;//每次取点的步长
		byte*		m_data;//数据空间指针

		DataElement() {
			m_size = -1;
			m_type = GT_FLOAT;
			m_stride = 0;
			m_data = nullptr;
		}
	};

	struct Statement {
		bool				 m_useBlend;//是否启用alpha混合模式
		bool				 m_enableTexture;//是否启用纹理贴图
		const Image*	     m_texture;//纹理贴图素材
		Image::TEXTURE_TYPE  m_texType;//纹理过滤
		byte				 m_alphaLimit;//大于此像素值才可以进行绘制

		DataElement			 m_vertexData;
		DataElement			 m_colorData;
		DataElement			 m_texCoordData;

		Statement() {
			m_useBlend = false;
			m_enableTexture = false;
			m_texture = nullptr;
			m_texType = Image::TX_REPEAT;
			m_alphaLimit = 0;
		}
	};

	//画布类,封装一些之后的图形API
	class Canvas {
	private:
		int			 m_width;
		int			 m_height;
		RGBA*		 m_buffer;

		Statement	 m_state;

	public:
		Canvas(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;
			m_state.m_useBlend = false;
			m_state.m_enableTexture = false;
		}
		~Canvas()
		{
		}

		//=========画布清洗============
		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;
		}
		//根据真正的背景值取pixel
		RGBA getColor(int x, int y) {
			if (x < 0 || x >= m_width || y < 0 || y >= m_height) {
				return RGBA(0, 0, 0, 0);
			}
			return m_buffer[y * m_width + x];
		}

		//=========画线算法Brensenhem===
		void drawLine(Point pt1,Point pt2);

		//=========线性插值Lerp=========
		inline RGBA colorLerp(RGBA _color1, RGBA _color2, float _scale) {
			RGBA _color;
			_color.m_r = _color.m_r + (float)(_color2.m_r - _color1.m_r) * _scale;
			_color.m_g = _color.m_g + (float)(_color2.m_g - _color1.m_g) * _scale;
			_color.m_b = _color.m_b + (float)(_color2.m_b - _color1.m_b) * _scale;
			_color.m_a = _color.m_a + (float)(_color2.m_a - _color1.m_a) * _scale;
			return _color;
		}

		//=========画三角形==============
		void drawTriange(Point p1, Point p2, Point p3);
		void drawTriangeFlat(Point pFlat1, Point pFlat2, Point pt);


		//=========判断三角形是否与屏幕相交======
		bool judgeInRect(Point p, GT_RECT _rect);
		bool judgeInTriangle(Point pt, std::vector<Point> _ptArray);


		//==========图片操作=============
		void drawImage(int _x, int _y, Image* _image);
		void setAlphaLimit(byte _limit) { m_state.m_alphaLimit = _limit; }
		void setBlend(bool _useBlend) { m_state.m_useBlend = _useBlend; }

		//===========纹理===============
		void enableTexture(bool _enable) { m_state.m_enableTexture = _enable; }
		void bindTexture(const Image* _image) { m_state.m_texture = _image; }
		void setTextureType(Image::TEXTURE_TYPE _type) { m_state.m_texType = _type; }
		inline floatV2 uvLerp(floatV2 _uv1, floatV2 _uv2, float _scale) {
			floatV2 _uv;
			_uv.x = _uv1.x + (_uv2.x - _uv1.x) * _scale;
			_uv.y = _uv1.y + (_uv2.y - _uv1.y) * _scale;
			return _uv;
		}

		//===========状态机接口===============
		void gtVertexPointer(int _size, DATA_TYPE _type, int _stride, byte* _data);
		void gtColorPointer(int _size, DATA_TYPE _type, int _stride, byte* _data);
		void gtTexCoordPointer(int _size, DATA_TYPE _type, int _stride, byte* _data);
		void gtDrawArray(DRAW_MODE _mode,int _first,int _count);//从first的点,画count个点
	};
}


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值