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


    目录

    什么是状态机?

    基于状态机模式进行重构

    Canvas.h源码


    什么是状态机

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

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

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

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

    状态机:

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

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

    为什么用状态机?

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

    基于状态机模式进行重构

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

    canvas.h:

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

    1. enum DATA_TYPE {
    2. GT_FLOAT=0,
    3. GT_INT=1
    4. };
    5. enum DRAW_MODE {
    6. GT_LINE=0,
    7. GL_TRIANGLE=1
    8. };
    9. struct DataElement {
    10. int m_size;
    11. DATA_TYPE m_type;
    12. int m_stride;//每次取点的步长
    13. byte* m_data;//数据空间指针
    14. DataElement() {
    15. m_size = -1;
    16. m_type = GT_FLOAT;
    17. m_stride = 0;
    18. m_data = nullptr;
    19. }
    20. };

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

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

    1. //===========状态机接口===============
    2. void gtVertexPointer(int _size, DATA_TYPE _type, int _stride, byte* _data);
    3. void gtColorPointer(int _size, DATA_TYPE _type, int _stride, byte* _data);
    4. void gtTexCoordPointer(int _size, DATA_TYPE _type, int _stride, byte* _data);
    5. void gtDrawArray(DRAW_MODE _mode,int _first,int _count);//从first的点,画count个点
    1. void Canvas::gtVertexPointer(int _size, DATA_TYPE _type, int _stride, byte* _data)
    2. {
    3. m_state.m_vertexData.m_size = _size;
    4. m_state.m_vertexData.m_type = _type;
    5. m_state.m_vertexData.m_stride = _stride;
    6. m_state.m_vertexData.m_data = _data;
    7. }
    8. void Canvas::gtColorPointer(int _size, DATA_TYPE _type, int _stride, byte* _data)
    9. {
    10. m_state.m_colorData.m_size = _size;
    11. m_state.m_colorData.m_type = _type;
    12. m_state.m_colorData.m_stride = _stride;
    13. m_state.m_colorData.m_data = _data;
    14. }
    15. void Canvas::gtTexCoordPointer(int _size, DATA_TYPE _type, int _stride, byte* _data)
    16. {
    17. m_state.m_texCoordData.m_size = _size;
    18. m_state.m_texCoordData.m_type = _type;
    19. m_state.m_texCoordData.m_stride = _stride;
    20. m_state.m_texCoordData.m_data = _data;
    21. }
    22. void Canvas::gtDrawArray(DRAW_MODE _mode, int _first, int _count)
    23. {
    24. }

    Canvas.h源码

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

    1. #pragma once
    2. #include "GTMATH.hpp"
    3. #include
    4. #include
    5. #include "Image.h"
    6. namespace GT {
    7. //点类
    8. class Point {
    9. public:
    10. int m_x;
    11. int m_y;
    12. RGBA m_color;
    13. floatV2 m_uv;
    14. Point(int _x = 0, int _y = 0, RGBA _color = RGBA(0, 0, 0, 0), floatV2 _uv = floatV2(0.0, 0.0)) {
    15. m_x = _x, m_y = _y, m_color = _color, m_uv = _uv;
    16. }
    17. ~Point() {}
    18. };
    19. enum DATA_TYPE {
    20. GT_FLOAT=0,
    21. GT_INT=1
    22. };
    23. enum DRAW_MODE {
    24. GT_LINE=0,
    25. GL_TRIANGLE=1
    26. };
    27. struct DataElement {
    28. int m_size;
    29. DATA_TYPE m_type;
    30. int m_stride;//每次取点的步长
    31. byte* m_data;//数据空间指针
    32. DataElement() {
    33. m_size = -1;
    34. m_type = GT_FLOAT;
    35. m_stride = 0;
    36. m_data = nullptr;
    37. }
    38. };
    39. struct Statement {
    40. bool m_useBlend;//是否启用alpha混合模式
    41. bool m_enableTexture;//是否启用纹理贴图
    42. const Image* m_texture;//纹理贴图素材
    43. Image::TEXTURE_TYPE m_texType;//纹理过滤
    44. byte m_alphaLimit;//大于此像素值才可以进行绘制
    45. DataElement m_vertexData;
    46. DataElement m_colorData;
    47. DataElement m_texCoordData;
    48. Statement() {
    49. m_useBlend = false;
    50. m_enableTexture = false;
    51. m_texture = nullptr;
    52. m_texType = Image::TX_REPEAT;
    53. m_alphaLimit = 0;
    54. }
    55. };
    56. //画布类,封装一些之后的图形API
    57. class Canvas {
    58. private:
    59. int m_width;
    60. int m_height;
    61. RGBA* m_buffer;
    62. Statement m_state;
    63. public:
    64. Canvas(int _width, int _height, void* _buffer) {
    65. if (_width <= 0 || _height <= 0) {
    66. m_width = -1;
    67. m_height = -1;
    68. m_buffer = nullptr;
    69. }
    70. m_width = _width;
    71. m_height = _height;
    72. m_buffer = (RGBA*)_buffer;
    73. m_state.m_useBlend = false;
    74. m_state.m_enableTexture = false;
    75. }
    76. ~Canvas()
    77. {
    78. }
    79. //=========画布清洗============
    80. void clear() {
    81. if (m_buffer != nullptr) {
    82. memset(m_buffer, 0, sizeof(RGBA) * m_width * m_height);
    83. }
    84. }
    85. //=========画点操作============
    86. void drawPoint(int x, int y, RGBA _color) {
    87. if (x < 0 || x >= m_width || y < 0 || y >= m_height) {
    88. return;
    89. }
    90. m_buffer[y * m_width + x] = _color;
    91. }
    92. //根据真正的背景值取pixel
    93. RGBA getColor(int x, int y) {
    94. if (x < 0 || x >= m_width || y < 0 || y >= m_height) {
    95. return RGBA(0, 0, 0, 0);
    96. }
    97. return m_buffer[y * m_width + x];
    98. }
    99. //=========画线算法Brensenhem===
    100. void drawLine(Point pt1,Point pt2);
    101. //=========线性插值Lerp=========
    102. inline RGBA colorLerp(RGBA _color1, RGBA _color2, float _scale) {
    103. RGBA _color;
    104. _color.m_r = _color.m_r + (float)(_color2.m_r - _color1.m_r) * _scale;
    105. _color.m_g = _color.m_g + (float)(_color2.m_g - _color1.m_g) * _scale;
    106. _color.m_b = _color.m_b + (float)(_color2.m_b - _color1.m_b) * _scale;
    107. _color.m_a = _color.m_a + (float)(_color2.m_a - _color1.m_a) * _scale;
    108. return _color;
    109. }
    110. //=========画三角形==============
    111. void drawTriange(Point p1, Point p2, Point p3);
    112. void drawTriangeFlat(Point pFlat1, Point pFlat2, Point pt);
    113. //=========判断三角形是否与屏幕相交======
    114. bool judgeInRect(Point p, GT_RECT _rect);
    115. bool judgeInTriangle(Point pt, std::vector _ptArray);
    116. //==========图片操作=============
    117. void drawImage(int _x, int _y, Image* _image);
    118. void setAlphaLimit(byte _limit) { m_state.m_alphaLimit = _limit; }
    119. void setBlend(bool _useBlend) { m_state.m_useBlend = _useBlend; }
    120. //===========纹理===============
    121. void enableTexture(bool _enable) { m_state.m_enableTexture = _enable; }
    122. void bindTexture(const Image* _image) { m_state.m_texture = _image; }
    123. void setTextureType(Image::TEXTURE_TYPE _type) { m_state.m_texType = _type; }
    124. inline floatV2 uvLerp(floatV2 _uv1, floatV2 _uv2, float _scale) {
    125. floatV2 _uv;
    126. _uv.x = _uv1.x + (_uv2.x - _uv1.x) * _scale;
    127. _uv.y = _uv1.y + (_uv2.y - _uv1.y) * _scale;
    128. return _uv;
    129. }
    130. //===========状态机接口===============
    131. void gtVertexPointer(int _size, DATA_TYPE _type, int _stride, byte* _data);
    132. void gtColorPointer(int _size, DATA_TYPE _type, int _stride, byte* _data);
    133. void gtTexCoordPointer(int _size, DATA_TYPE _type, int _stride, byte* _data);
    134. void gtDrawArray(DRAW_MODE _mode,int _first,int _count);//从first的点,画count个点
    135. };
    136. }

  • 相关阅读:
    【Lilishop商城】No2-6.确定软件架构搭建五(本篇包括定时任务xxl-job)
    cyber搜索引擎
    EAV模型(实体-属性-值)的设计和低代码的处理方案(1)
    C++的输入与输出
    4.JS高级和promise
    CentOS7.9 安装postgresql
    5G相关信息
    清理 Ubuntu 系统的 4 个简单步骤
    TRex学习之旅十
    Springboot中的三层架构
  • 原文地址:https://blog.csdn.net/Jason6620/article/details/127948542