Browse Source

feat: 添加状态机相关接口和解释

nicetry12138 1 year ago
parent
commit
ef535b0bac

+ 38 - 0
OpenGL/README.md

@@ -1336,3 +1336,41 @@ _canvas->drawTriangle(
 
 ## 图形学状态机接口封装
 
+什么是状态机
+
+1. 记录状态参数
+   - 信息记录:顶点信息、Image信息等
+   - 状态记录:是否启用 Blender 等
+2. 更改状态参数
+   - 一开始绑定 A 贴图绘制三角形,随后绑定 B 贴图绘制另一个三角新
+3. 使用状态参数做事
+   - 根据设定的状态参数,绘制对应内容
+
+也就是主要状态参数设置的对,具体如何做交给对应的模块去做就行
+
+```cpp
+// OpenGL 中的状态机设置
+
+glEnable(GL_DEPTH_TEST);
+glEnable(GL_BLEND);
+glEnable(GL_CULL_FACE);
+glEnable(GL_TEXTURE_2D);
+
+glIsEnabled(GL_DEPTH_TEST);
+glIsEnabled(GL_BLEND);
+glIsEnabled(GL_CULL_FACE);
+glIsEnabled(GL_TEXTURE_2D);
+```
+
+1. 性能优化  
+    - 状态机模型允许 `OpenGL` 在运行时高效管理和修改状态。由于状态一旦设定,除非明确改变,否则会一直保持,这减少了重复设置相同状态的需要,从而提高了图形渲染的效率。例如,设定纹理、着色器或渲染参数后,可以连续渲染多个对象,而不需要每次渲染时都重新设置这些参数
+
+2. 简化 API 设计
+   - 通过使用状态机,`OpenGL` `API` 能够通过一系列的简单命令来控制复杂的渲染操作。这样的设计使得API相对简洁,用户只需要更改与当前任务相关的状态即可,而不用在每次调用绘图函数时提供所有的细节
+
+3. 增加灵活性
+   - 状态机模型使开发者能够精确控制渲染流程中的各个方面,可以细粒度地调整图形的每个属性,如颜色、材质、灯光和阴影等。这种控制的灵活性对于开发高质量的图形应用是非常重要的
+
+4. 减少状态改变的开销
+   - 在图形渲染过程中,频繁地改变状态是一项耗费性能的操作。通过维护一个持续的状态环境,可以最小化状态变化的次数,从而减少 `CPU` 和 `GPU` 之间的通信开销,提高整体性能
+

+ 59 - 10
OpenGL/src/WindowsProjectTest/WindowsProjectTest/Canvas.cpp

@@ -54,10 +54,10 @@ namespace GT {
 
 			RGBA pointColor;
 
-			if (m_enableTexture && m_texture != nullptr) {
+			if (m_State.m_enableTexture && m_State.m_texture != nullptr) {
 				// 开启贴图 并且贴图有效 使用贴图颜色
 				floatV2 uv = uvLerp(pt1.m_uv, pt2.m_uv, (float)index / sumStep);
-				pointColor = m_texture->GetColorByUV(uv, m_textureType);
+				pointColor = m_State.m_texture->GetColorByUV(uv, m_State.m_textureType);
 			}
 			else {
 				pointColor = colorLerp(pt1.m_color, pt2.m_color, (float)index / sumStep);
@@ -190,22 +190,71 @@ namespace GT {
 
 	void Canvas::setBlend(bool inUseBlend)
 	{
-		m_UseBlend = inUseBlend;
+		m_State.m_UseBlend = inUseBlend;
 	}
 
 	void Canvas::enableTexture(bool inEnable)
 	{
-		m_enableTexture = inEnable;
+		m_State.m_enableTexture = inEnable;
 	}
 
 	void Canvas::bindTexture(Image* inImage)
 	{
-		m_texture = inImage;
+		m_State.m_texture = inImage;
 	}
 
 	void Canvas::setTextureType(Image::TEXTURE_TYPE inType)
 	{
-		m_textureType = inType;
+		m_State.m_textureType = inType;
+	}
+
+	void Canvas::gtVertexPointer(int inSize, DATA_TYPE inType, int inStride, byte* inData)
+	{
+		m_State.m_vertextData.m_size = inSize;
+		m_State.m_vertextData.m_type = inType;
+		m_State.m_vertextData.m_stride = inStride;
+		m_State.m_vertextData.m_data = inData;
+	}
+
+	void Canvas::gtColorPointer(int inSize, DATA_TYPE inType, int inStride, byte* inData)
+	{
+		m_State.m_colorData.m_size = inSize;
+		m_State.m_colorData.m_type = inType;
+		m_State.m_colorData.m_stride = inStride;
+		m_State.m_colorData.m_data = inData;
+	}
+
+	void Canvas::gtTexCoordPointer(int inSize, DATA_TYPE inType, int inStride, byte* inData)
+	{
+		m_State.m_texCoordData.m_size = inSize;
+		m_State.m_texCoordData.m_type = inType;
+		m_State.m_texCoordData.m_stride = inStride;
+		m_State.m_texCoordData.m_data = inData;
+	}
+
+	void Canvas::gtDrawArray(DRAW_MODE inMode, int inFirstIndex, int inCount)
+	{
+		switch (inMode)
+		{
+		case GT::GT_LINE: {
+			Point pt1, pt2;
+			byte* vertexData = m_State.m_vertextData.m_data;
+			byte* colorData = m_State.m_colorData.m_data;
+			byte* texCoordData = m_State.m_texCoordData.m_data;
+			for (int i = 0; i < inCount; i += 2) {
+				float* vertexDataFloat = (float*)vertexData;
+				pt1.m_x = vertexDataFloat[0];
+				pt1.m_y = vertexDataFloat[1];
+			}
+			break;
+		}
+		case GT::GT_TRIANGLE: {
+
+			break;
+		}
+		default:
+			break;
+		}
 	}
 
 	void Canvas::drawTriangleFlat(const Point& pt1, const Point& pt2, const Point& pt)
@@ -229,9 +278,9 @@ namespace GT {
 		int posY = pt.m_y;
 
 		// 限制绘制区域 计算 posY 和 step 的值 防止出现 y = 1000000 或者 y = -1000000
-		if (!GT::UTool::inRange(pt.m_y, 0, m_Height) || !GT::UTool::inRange(pt1.m_y, 0, m_Height)) {
-			int pos1Y = GT::UTool::clamp(pt1.m_y, 0, m_Height);
-			posY = GT::UTool::clamp(pt.m_y, 0, m_Height);
+		if (!GT::UTool::inRange(pt.m_y, 0.0f, m_Height * 1.0f) || !GT::UTool::inRange(pt1.m_y, 0.0f, m_Height * 1.0f)) {
+			int pos1Y = GT::UTool::clamp(pt1.m_y, 0.0f, m_Height * 1.0f);
+			posY = GT::UTool::clamp(pt.m_y, 0.0f, m_Height * 1.0f);
 			step = abs(posY - pt.m_y);
 			totalStemp = abs(pt.m_y - pt1.m_y) - abs(pt1.m_y - pos1Y);
 		}
@@ -346,7 +395,7 @@ namespace GT {
 		for (int u = 0; u < inImage->GetWidth(); ++u) {
 			for (int v = 0; v < inImage->GetHeight(); ++v) {
 				const RGBA srcColor = inImage->GetColor(u, v);
-				if (!m_UseBlend) {
+				if (!m_State.m_UseBlend) {
 					drawPoint(Point(inX + u, inY + v, srcColor));
 				}
 				else {

+ 53 - 4
OpenGL/src/WindowsProjectTest/WindowsProjectTest/Canvas.h

@@ -6,6 +6,49 @@
 #include "Image.h"
 
 namespace GT {
+	enum DATA_TYPE {
+		GT_FLOAT = 0,
+		GT_INT = 1,
+	};
+
+	enum DRAW_MODE {
+		GT_LINE = 0,
+		GT_TRIANGLE = 1
+	};
+
+	struct DataElement
+	{
+		int			m_size = 0;			// 数据长度
+		DATA_TYPE	m_type;				// 数据类型
+		int			m_stride;			// 步长
+		byte*		m_data{nullptr};	// 数据
+
+		DataElement() {
+			m_size = 0;
+			m_type = DATA_TYPE::GT_FLOAT;
+			m_data = nullptr;
+			m_stride = 0;
+		}
+	};
+
+	// 状态相关
+	struct Statement {
+		bool					m_UseBlend = true; // 是否进行颜色混合
+		bool					m_enableTexture = true;	// 是否启用纹理贴图
+		Image*					m_texture{ nullptr };	// 绘制剩下顶点的时候 使用那种图片
+		Image::TEXTURE_TYPE		m_textureType = Image::TEXTURE_TYPE::TX_REPEAT;	// 纹理绘制
+
+		DataElement				m_vertextData;		// 顶点信息
+		DataElement				m_colorData;		// 颜色信息
+		DataElement				m_texCoordData;		// 贴图信息
+
+		Statement() {
+			m_UseBlend = true;
+			m_enableTexture = false;
+			m_textureType = Image::TEXTURE_TYPE::TX_REPEAT;
+			m_texture = nullptr;
+		}
+	};
 
 	// 操作画布的类
 	class Canvas
@@ -16,11 +59,8 @@ namespace GT {
 		RGBA* m_Buffer{ nullptr };
 
 		byte m_alphaLimit{ 0 }; // 大于此值的像素才可以进行绘制
-		bool m_UseBlend = true; // 是否进行颜色混合
 
-		bool m_enableTexture = true;	// 是否启用纹理贴图
-		Image* m_texture{ nullptr };	// 绘制剩下顶点的时候 使用那种图片
-		Image::TEXTURE_TYPE m_textureType = Image::TEXTURE_TYPE::TX_REPEAT;	// 纹理绘制
+		Statement m_State;
 	public: 
 		Canvas(int _width, int _height, void* _buffer) {
 			if (_width <= 0 || _height <= 0) {
@@ -75,6 +115,15 @@ namespace GT {
 
 		void setTextureType(Image::TEXTURE_TYPE inType);
 
+		// 模拟 glVertexPointer
+		void gtVertexPointer(int inSize, DATA_TYPE inType, int inStride, byte* inData);
+		// 模拟 gtColorPointer
+		void gtColorPointer(int inSize, DATA_TYPE inType, int inStride, byte* inData);
+		// 模拟 gtTexCoordPointer
+		void gtTexCoordPointer(int inSize, DATA_TYPE inType, int inStride, byte* inData);
+
+		void gtDrawArray(DRAW_MODE inMode, int inFirstIndex, int inCount);
+
 	protected:
 		// 平底平顶三角形绘制 pt1 和 pt2 是平底或平顶的两点,pt 是单独的一个顶点
 		void drawTriangleFlat(const Point& pt1, const Point& pt2, const Point& pt);

+ 3 - 3
OpenGL/src/WindowsProjectTest/WindowsProjectTest/GTMATH.hpp

@@ -81,11 +81,11 @@ namespace GT
 	struct Point
 	{
 	public:
-		int m_x;
-		int m_y;
+		float m_x;
+		float 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.0f, 0.0f))
+		Point(float _x = 0.0f, float _y = 0.0f, RGBA _color = RGBA(0, 0, 0, 0), floatV2 _uv = floatV2(0.0f, 0.0f))
 		{
 			m_x = _x;
 			m_y = _y;