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

news2024/12/30 2:19:16

目录

什么是状态机?

基于状态机模式进行重构

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个点
	};
}


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/20822.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

RabbitMQ------延迟队列(整合SpringBoot以及使用延迟插件实现真正延时)(七)

RabbitMQ------延迟队列&#xff08;七&#xff09; 延迟队列 延迟队列&#xff0c;内部是有序的&#xff0c;特点&#xff1a;延时属性。 简单讲&#xff1a;延时队列是用来存放需要在指定时间被处理的元素队列。 是基于死信队列的消息过期场景。 适用场景 1.订单在十分钟…

Linux(centos7)安装MySQL5.7

Linux 安装MySQL5.7 数据库 所有的安装方式是基于手动式的安装&#xff0c;也就是整体的下载然后配置 rpm与yum之间的关系 rpm 是Linux 免除编译安装带来的安装方式&#xff0c;而yum 是在rpm 上面的进一步的优化&#xff0c;换句话说yum 既包含了rpm 的简单安装&#xff0c…

百度地图自定义覆盖物(html)格式

<style type"text/css"> body, html{ width: 100%; height: 100%; overflow: hidden; margin: 0; font-family: "微软雅黑"; display: flex; justify-content: space-between; } #cont…

使用html+css实现一个静态页面(厦门旅游网站制作6个页面) 旅游网页设计制作 HTML5期末考核大作业,网站——美丽家乡。 学生旅行 游玩 主题住宿网页

&#x1f468;‍&#x1f393;静态网站的编写主要是用 HTML DⅣV CSSJS等来完成页面的排版设计&#x1f469;‍&#x1f393;&#xff0c;一般的网页作业需要融入以下知识点&#xff1a;div布局、浮动定位、高级css、表格、表单及验证、js轮播图、音频视频Fash的应用、uli、下拉…

FL Studio2023水果完整中文版音乐制作软件

FL Studio2023水果中文版是一款由 Image Line 公司研发几近完美的虚拟音乐工作站,同时也是知名的音乐制作软件。它让你的计算机就像是全功能的录音室&#xff0c;漂亮的大混音盘&#xff0c;先进的创作工具&#xff0c;让你的音乐突破想象力的限制。它可以播放由你指定或加入的…

IP包头分析

数据来源 IP包头长度 ip包头的长度在20-60个字节间&#xff0c;一般是20字节&#xff08;固定部分&#xff09;&#xff0c;可选项最大是40个字节&#xff08;比较少用&#xff09;。 第一行 版本 就是指出IP数据包是什么版本&#xff1b;常见的版本就是0100 IPV4和 0110 IPV6…

机器学习中基本符号表示和常用术语

目录一. 基本符号表示二. 常用术语1. 精准率计算&#xff08;precision&#xff09;2.召回率计算&#xff08;recall&#xff09;3.准确率的计算&#xff08;accuracy&#xff09;4.F1 Score5. G分数6.一. 基本符号表示 TP &#xff08;true positive&#xff09;&#xff1a;预…

【Python】基础语法(安装,常变量,类型,注释,运算符)

目录python环境搭建安装Python安装pycharmpython基础语法常量和表达式变量和数据类型变量数据类型注释输入输出运算符算术运算符关系运算符逻辑运算符赋值运算符xdm,最近更新一些学习Python基础知识的内容,感谢支持!python环境搭建 俗话说工欲善其事必先利其器,要想学习Python开…

新知实验室TRTC初体验

小记 一次偶然的邂逅,让我知道了TRTC实时音视频这个神奇的东西,于是便开始研究起来这个鬼东西,本以为是一个很简单的东西,调用一下SDK就完事了 , 谁知道它的文档并不是很齐全,这一点还需要多多努力啊!!! 正文 实时音视频&#xff08;TRTC&#xff09; 是腾讯云提供的一套低…

现代对称密码

乘积密码 因为语言特性&#xff0c;用代替和置换是不安全的&#xff0c;可以考虑用多次的加密增强密码强度。多次加密想要提高密码强度&#xff0c;要求多次加密不能成为一个群&#xff0c;那么加密就可以被重复并且组合复杂度会增加。 分组密码 分组密码就是把明文分组后进…

Linux进阶-Shell编程与环境变量

目录 定义变量&#xff1a; 使用变量&#xff1a; 将命令的结果赋值给变量&#xff1a; 删除变量&#xff1a;unset 退出当前进程&#xff1a;exit 读取从键盘输入的数据 &#xff1a;read 对整数进行数字运算&#xff1a;(()) 逻辑与或&#xff1a; 检测某个条件是否成…

【Java八股文总结】之MySQL数据库

文章目录数据库一、基本概念二、MySQL数据库2.1 MySQL基础1、MySQL数据库的优点&#xff1f;2、MySQL支持的数据类型有&#xff1f;Q&#xff1a;varchar 和 char 的区别&#xff1f;Q&#xff1a;blob 和 text 的区别&#xff1f;Q&#xff1a;datetime 和 timestamp 的区别&a…

DI依赖注入-P8,P9,P10,P11

1.构造器注入 之前写过了~~~~ 2.Set方式注入【重点】 3.拓展方式注入 2.Set方式注入【重点】 【环境搭建】 1.复杂类型 2.真实测试对象 四个文件 Student实体类的创建&#xff1a; 主要是依据官方文档来建立。那个Address也是为了测试不同的类型&#xff0c;而创建的引…

攻防世界misc2-1

misc2-1 题目描述&#xff1a;无 题目环境&#xff1a;https://download.csdn.net/download/m0_59188912/87094620 打开图片&#xff0c;发现无法显示。 使用winhex打开&#xff0c;从其中一段看出这是逆序图片。 使用python脚本将其正序排列。 脚本源码&#xff1a; f1open(‘…

5G无线技术基础自学系列 | SA及NSA组网架构

素材来源&#xff1a;《5G无线网络规划与优化》 一边学习一边整理内容&#xff0c;并与大家分享&#xff0c;侵权即删&#xff0c;谢谢支持&#xff01; 附上汇总贴&#xff1a;5G无线技术基础自学系列 | 汇总_COCOgsta的博客-CSDN博客 3GPP为新空中接口定义了两种部署配置&a…

操作系统笔记

文章目录一、操作系统的定义1.1 操作系统的功能和目标1.2 操作系统的特征1.3 操作系统的发展和分类1.4 操作系统的运行机制1.5 操作系统内核1.6 操作系统的体系结构二、中断机制中断和异常三、系统调用3.1 系统调用的分类&#xff08;按功能分配&#xff09;3.2 系统调用和库函…

整夜我的背影是一条踏往星空的道路

Brigit Pegeen Kelly&#xff0c;1951 - 2016.08.14&#xff0c;美国诗人、教师&#xff0c;在加利福尼亚州帕洛阿尔托出生&#xff0c;在印第安纳南部长达&#xff0c;成年后的大部分时间都在伊利诺州中部度过。一位非常注重隐私的女性&#xff0c;她的生活很少为人所知。[1][…

计算机基础学习(好文必看)

好长时间没发文章了&#xff0c;主要是以输入为主。 那么&#xff0c;给小伙伴们推荐一些计算机基础学习的知识&#xff0c;自己感觉挺不错的。 计算机基础学习&#xff1a; 1. 小林师傅是一位宝藏博主&#xff0c;非常厉害&#xff0c;各大平台都有他的文章&#xff0c;我是…

Day08--自定义组件的样式

提纲挈领&#xff1a; ************************************************************************************************************ 我的操作&#xff1a; 1》在app.wxss里面定义一个全局样式&#xff1a; 2》在home.wxml里面使用全局样式。 3》在test2.wxml里面使用…

Prometheus系列(一)安装

1 安装 Prometheus Server 官网&#xff1a;https://prometheus.io/ 下载&#xff1a;https://prometheus.io/download/ 手册&#xff1a;https://prometheus.io/docs/introduction/overview/ Prometheus 基于 Golang 编写&#xff0c;编译后的软件包&#xff0c;不依赖于任何的…