当前位置:   article > 正文

跟着cherno手搓游戏引擎【29】Batch简单合批

跟着cherno手搓游戏引擎【29】Batch简单合批

思路:

CPUGPU都开辟同样大小的一大块内存(为了存储顶点信息)

索引在程序运行时生成对应规则后绑定到索引缓冲中

动态生成顶点信息(现在改成Drawquad只是确定图形顶点的位置)

然后在Endscene,将CPU的动态生成的顶点数据上传给GPU,然后再绘制出来

所以,就是根据所绘制的物体,动态生成索引缓冲区,然后根据索引缓冲区一次性绘制多个物体

实现:

Renderer2D.h:

  1. #pragma once
  2. #include "OrthographicCamera.h"
  3. #include"Texture.h"
  4. namespace YOTO {
  5. class Renderer2D
  6. {
  7. public:
  8. //为什么渲染器是静态的:
  9. static void Init();
  10. static void ShutDown();
  11. static void BeginScene(const OrthographicCamera& camera);
  12. static void EndScene();
  13. static void Flush();
  14. static void DrawQuad(const glm::vec2& position, const glm::vec2& size ,const glm::vec4& color);
  15. static void DrawQuad(const glm::vec3& position, const glm::vec2& size ,const glm::vec4& color);
  16. static void DrawQuad(const glm::vec2& position, const glm::vec2& size ,const Ref<Texture2D> texture,float tilingFactor=1.0f,const glm::vec4& tintColor=glm::vec4(1.0f));
  17. static void DrawQuad(const glm::vec3& position, const glm::vec2& size ,const Ref<Texture2D> texture,float tilingFactor=1.0f,const glm::vec4& tintColor=glm::vec4(1.0f));
  18. static void DrawRotatedQuad(const glm::vec2& position, const glm::vec2& size, float rotation,const glm::vec4& color);
  19. static void DrawRotatedQuad(const glm::vec3& position, const glm::vec2& size, float rotation,const glm::vec4& color);
  20. static void DrawRotatedQuad(const glm::vec2& position, const glm::vec2& size, float rotation,const Ref<Texture2D> texture, float tilingFactor = 1.0f, const glm::vec4& tintColor = glm::vec4(1.0f));
  21. static void DrawRotatedQuad(const glm::vec3& position, const glm::vec2& size, float rotation,const Ref<Texture2D> texture, float tilingFactor = 1.0f, const glm::vec4& tintColor = glm::vec4(1.0f));
  22. };
  23. }

Renderer2D.cpp:

  1. #include "ytpch.h"
  2. #include "Renderer2D.h"
  3. #include"VertexArray.h"
  4. #include"Shader.h"
  5. //#include "Platform/OpenGL/OpenGLShader.h"
  6. #include <glm/gtc/matrix_transform.hpp>
  7. #include "RenderCommand.h"
  8. namespace YOTO {
  9. /// <summary>
  10. /// 为什么QuadVertex的指针可以作为void*data传入glBufferSubData:
  11. /// SetLayout配置的就是这三个的顺序,因为glm内部用float实现
  12. /// 相当于前三个float是Position,之后四个float组成的Color,
  13. /// 最后是两个float组成的TexCoord
  14. /// </summary>
  15. struct QuadVertex {
  16. glm::vec3 Position;
  17. glm::vec4 Color;
  18. glm::vec2 TexCoord;
  19. //,纹理Id,
  20. };
  21. struct Renderer2DData {
  22. const uint32_t MaxQuads = 10000;
  23. const uint32_t MaxVertices = MaxQuads * 4;
  24. const uint32_t MaxIndices = MaxQuads * 6;
  25. //顶点数组
  26. Ref<VertexArray> QuadVertexArray;
  27. //定带你缓冲
  28. Ref<VertexBuffer> QuadVertexBuffer;
  29. //Ref<Shader> FlatColorShader;
  30. //Shader
  31. Ref<Shader> TextureShader;
  32. //纹理
  33. Ref<Texture2D> WhiteTexture;
  34. //记录索引
  35. uint32_t QuadIndexCount =0;
  36. QuadVertex* QuadVertexBufferBase=nullptr;
  37. QuadVertex* QuadVertexBufferPtr= nullptr;
  38. };
  39. //CPU开辟的大内存
  40. static Renderer2DData s_Data;
  41. void Renderer2D::Init()
  42. {
  43. YT_PROFILE_FUNCTION();
  44. //---------------------顶点数组--------------------------
  45. //创建顶点数组
  46. s_Data.QuadVertexArray = VertexArray::Create();
  47. // 创建顶点缓冲区,先在GPU开辟一块s_Data.MaxVertices * sizeof(QuadVertex)大小的内存
  48. // 与cpu对应大,是为了传输顶点数据
  49. //---------------------顶点缓冲区--------------------------
  50. s_Data.QuadVertexBuffer =VertexBuffer::Create(s_Data.MaxVertices*sizeof(QuadVertex));
  51. s_Data.QuadVertexBuffer->SetLayout({
  52. {ShaderDataType::Float3,"a_Position"},
  53. {ShaderDataType::Float4,"a_Color"},
  54. {ShaderDataType::Float2,"a_TexCoord"}
  55. });
  56. //顶点数组添加顶点缓冲区,并且在这个缓冲区中设置布局
  57. s_Data.QuadVertexArray->AddVertexBuffer(s_Data.QuadVertexBuffer);
  58. // 在CPU开辟存储s_Data.MaxVertices个的QuadVertex的内存
  59. s_Data.QuadVertexBufferBase = new QuadVertex[s_Data.MaxVertices];
  60. //---------------------索引缓冲区--------------------------
  61. //开辟一块索引缓冲区
  62. uint32_t* quadIndices = new uint32_t[s_Data.MaxIndices];
  63. uint32_t offset = 0; //配置索引
  64. for (uint32_t i = 0; i < s_Data.MaxIndices; i += 6) {
  65. quadIndices[i + 0] = offset + 0;
  66. quadIndices[i + 1] = offset + 1;
  67. quadIndices[i + 2] = offset + 2;
  68. quadIndices[i + 3] = offset + 2;
  69. quadIndices[i + 4] = offset + 3;
  70. quadIndices[i + 5] = offset + 0;
  71. offset += 4;
  72. }
  73. //创建索引缓冲区
  74. Ref<IndexBuffer> quardIB;
  75. quardIB =IndexBuffer::Create(quadIndices, s_Data.MaxIndices);
  76. s_Data.QuadVertexArray->AddIndexBuffer(quardIB);
  77. delete[] quadIndices; // cpu上传到gpu上了可以删除cpu的索引数据块了
  78. //---------------------纹理--------------------------
  79. // 创建一个白色Texture
  80. s_Data.WhiteTexture = Texture2D::Create(1, 1);
  81. uint32_t whiteTextureData = 0xffffffff;
  82. s_Data.WhiteTexture->SetData(&whiteTextureData, sizeof(uint32_t));
  83. //---------------------着色器--------------------------
  84. //加载shader,并传入shader参数
  85. s_Data.TextureShader= Shader::Create("assets/shaders/Texture.glsl");
  86. s_Data.TextureShader->Bind();
  87. s_Data.TextureShader->SetInt("u_Texture", 0);
  88. }
  89. void Renderer2D::ShutDown()
  90. {
  91. YT_PROFILE_FUNCTION();
  92. //delete s_Data;
  93. }
  94. void Renderer2D::BeginScene(const OrthographicCamera& camera)
  95. {
  96. YT_PROFILE_FUNCTION();
  97. s_Data.TextureShader->Bind();
  98. s_Data.TextureShader->SetMat4("u_ViewProjection", camera.GetViewProjectionMatrix());
  99. // 相当于初始化此帧要绘制的索引数量,上传的顶点数据
  100. s_Data.QuadIndexCount = 0;
  101. //指针指向首部
  102. s_Data.QuadVertexBufferPtr = s_Data.QuadVertexBufferBase;
  103. }
  104. void Renderer2D::EndScene()
  105. {
  106. YT_PROFILE_FUNCTION();
  107. // 计算当前绘制需要多少个顶点数据,注意这里是8!!!!!!
  108. uint32_t dataSize = (uint8_t*)s_Data.QuadVertexBufferPtr - (uint8_t*)s_Data.QuadVertexBufferBase;
  109. // 截取部分CPU的顶点数据上传OpenGL,
  110. s_Data.QuadVertexBuffer->SetData(s_Data.QuadVertexBufferBase, dataSize);
  111. Flush();
  112. }
  113. void Renderer2D::Flush()
  114. {
  115. RenderCommand::DrawIndexed(s_Data.QuadVertexArray, s_Data.QuadIndexCount);
  116. }
  117. void Renderer2D::DrawQuad(const glm::vec2& position, const glm::vec2& size, const glm::vec4& color)
  118. {
  119. DrawQuad({ position.x,position.y,0.0f }, size, color);
  120. }
  121. void Renderer2D::DrawQuad(const glm::vec3& position, const glm::vec2& size, const glm::vec4& color)
  122. {
  123. YT_PROFILE_FUNCTION();
  124. //s_Data.FlatColorShader->Bind();
  125. //s_Data.FlatColorShader->SetFloat4("u_Color", color);
  126. //s_Data.TextureShader->Bind();
  127. s_Data.QuadVertexBufferPtr->Position = position;
  128. s_Data.QuadVertexBufferPtr->Color = color;
  129. s_Data.QuadVertexBufferPtr->TexCoord = {0.0f,0.0f};
  130. s_Data.QuadVertexBufferPtr++;
  131. s_Data.QuadVertexBufferPtr->Position = { position.x+size.x,position.y,0.0f};
  132. s_Data.QuadVertexBufferPtr->Color = color;
  133. s_Data.QuadVertexBufferPtr->TexCoord = { 1.0f,0.0f };
  134. s_Data.QuadVertexBufferPtr++;
  135. s_Data.QuadVertexBufferPtr->Position = { position.x + size.x,position.y + size.y,0.0f };
  136. s_Data.QuadVertexBufferPtr->Color = color;
  137. s_Data.QuadVertexBufferPtr->TexCoord = { 1.0f,1.0f };
  138. s_Data.QuadVertexBufferPtr++;
  139. s_Data.QuadVertexBufferPtr->Position = { position.x,position.y+size.y,0.0f };
  140. s_Data.QuadVertexBufferPtr->Color = color;
  141. s_Data.QuadVertexBufferPtr->TexCoord = { 0.0f,1.0f };
  142. s_Data.QuadVertexBufferPtr++;
  143. s_Data.QuadIndexCount += 6;
  144. /*s_Data.TextureShader->SetFloat4("u_Color", color);
  145. s_Data.TextureShader->SetFloat("m_TilingFactor", 1.0f);
  146. s_Data.WhiteTexture->Bind();*/
  147. //glm::mat4 transform = glm::translate(glm::mat4(1.0f), position) /**rotation*/ * glm::scale(glm::mat4(1.0f), {size.x,size.y,1.0f});
  148. //s_Data.TextureShader->SetMat4("u_Transform", transform);
  149. //s_Data.QuadVertexArray->Bind();
  150. //RenderCommand::DrawIndexed(s_Data.QuadVertexArray);
  151. }
  152. void Renderer2D::DrawQuad(const glm::vec2& position, const glm::vec2& size, const Ref<Texture2D> texture, float tilingFactor, const glm::vec4& tintColor)
  153. {
  154. DrawQuad({ position.x,position.y,0.0f }, size, texture, tilingFactor, tintColor);
  155. }
  156. void Renderer2D::DrawQuad(const glm::vec3& position, const glm::vec2& size, const Ref<Texture2D> texture, float tilingFactor, const glm::vec4& tintColor)
  157. {
  158. YT_PROFILE_FUNCTION();
  159. //s_Data.TextureShader->Bind();
  160. s_Data.TextureShader->SetFloat4("u_Color", tintColor);
  161. s_Data.TextureShader->SetFloat("m_TilingFactor",tilingFactor);
  162. texture->Bind();
  163. glm::mat4 transform = glm::translate(glm::mat4(1.0f), position) /**rotation*/ * glm::scale(glm::mat4(1.0f), { size.x,size.y,1.0f });
  164. s_Data.TextureShader->SetMat4("u_Transform", transform);
  165. s_Data.QuadVertexArray->Bind();
  166. RenderCommand::DrawIndexed(s_Data.QuadVertexArray);
  167. }
  168. void Renderer2D::DrawRotatedQuad(const glm::vec2& position, const glm::vec2& size, float rotation, const glm::vec4& color)
  169. {
  170. DrawRotatedQuad({ position.x,position.y,0.0f }, size, rotation,color);
  171. }
  172. void Renderer2D::DrawRotatedQuad(const glm::vec3& position, const glm::vec2& size, float rotation, const glm::vec4& color)
  173. {
  174. YT_PROFILE_FUNCTION();
  175. s_Data.TextureShader->SetFloat4("u_Color", color);
  176. s_Data.TextureShader->SetFloat("m_TilingFactor", 1.0f);
  177. s_Data.WhiteTexture->Bind();
  178. glm::mat4 transform = glm::translate(glm::mat4(1.0f), position) * glm::rotate(glm::mat4(1.0f), rotation, {0.0f,0.0f,1.0f}) * glm::scale(glm::mat4(1.0f), { size.x,size.y,1.0f });
  179. s_Data.TextureShader->SetMat4("u_Transform", transform);
  180. s_Data.QuadVertexArray->Bind();
  181. RenderCommand::DrawIndexed(s_Data.QuadVertexArray);
  182. }
  183. void Renderer2D::DrawRotatedQuad(const glm::vec2& position, const glm::vec2& size, float rotation, const Ref<Texture2D> texture, float tilingFactor, const glm::vec4& tintColor)
  184. {
  185. DrawRotatedQuad({ position.x,position.y,0.0f }, size, rotation, texture, tilingFactor, tintColor);
  186. }
  187. void Renderer2D::DrawRotatedQuad(const glm::vec3& position, const glm::vec2& size, float rotation, const Ref<Texture2D> texture, float tilingFactor, const glm::vec4& tintColor)
  188. {
  189. YT_PROFILE_FUNCTION();
  190. //s_Data.TextureShader->Bind();
  191. s_Data.TextureShader->SetFloat4("u_Color", tintColor);
  192. s_Data.TextureShader->SetFloat("m_TilingFactor", tilingFactor);
  193. texture->Bind();
  194. glm::mat4 transform = glm::translate(glm::mat4(1.0f), position) * glm::rotate(glm::mat4(1.0f), rotation, { 0.0f,0.0f,1.0f }) * glm::scale(glm::mat4(1.0f), { size.x,size.y,1.0f });
  195. s_Data.TextureShader->SetMat4("u_Transform", transform);
  196. s_Data.QuadVertexArray->Bind();
  197. RenderCommand::DrawIndexed(s_Data.QuadVertexArray);
  198. }
  199. }

Buffer.h:添加SetData和Create方法:

  1. #pragma once
  2. namespace YOTO {
  3. enum class ShaderDataType{
  4. None=0,
  5. Float,Float2,Float3,Float4,
  6. Mat3,Mat4,
  7. Int,Int2,Int3,Int4,
  8. Bool,
  9. };
  10. static uint32_t ShaderDataTypeSize(ShaderDataType type) {
  11. switch (type)
  12. {
  13. case YOTO::ShaderDataType::Float:
  14. return 4;
  15. break;
  16. case YOTO::ShaderDataType::Float2:
  17. return 4*2;
  18. break;
  19. case YOTO::ShaderDataType::Float3:
  20. return 4*3;
  21. break;
  22. case YOTO::ShaderDataType::Float4:
  23. return 4*4;
  24. break;
  25. case YOTO::ShaderDataType::Mat3:
  26. return 4*3*3;
  27. break;
  28. case YOTO::ShaderDataType::Mat4:
  29. return 4*4*4;
  30. break;
  31. case YOTO::ShaderDataType::Int:
  32. return 4;
  33. break;
  34. case YOTO::ShaderDataType::Int2:
  35. return 4*2;
  36. break;
  37. case YOTO::ShaderDataType::Int3:
  38. return 4*3;
  39. break;
  40. case YOTO::ShaderDataType::Int4:
  41. return 4*4;
  42. break;
  43. case YOTO::ShaderDataType::Bool:
  44. return 1;
  45. break;
  46. }
  47. YT_CORE_ASSERT(false, "未知的ShaderDataType!");
  48. return 0;
  49. }
  50. struct BufferElement {
  51. std::string Name;
  52. ShaderDataType Type;
  53. uint32_t Size;
  54. uint32_t Offset;
  55. bool Normalized;
  56. BufferElement(){}
  57. BufferElement(ShaderDataType type, const std::string& name,bool normalized=false)
  58. :Name(name), Type(type), Size(ShaderDataTypeSize(type)), Offset(0), Normalized(normalized){}
  59. uint32_t GetComponentCount() const{
  60. switch (Type)
  61. {
  62. case YOTO::ShaderDataType::Float:
  63. return 1;
  64. break;
  65. case YOTO::ShaderDataType::Float2:
  66. return 2;
  67. break;
  68. case YOTO::ShaderDataType::Float3:
  69. return 3;
  70. break;
  71. case YOTO::ShaderDataType::Float4:
  72. return 4;
  73. break;
  74. case YOTO::ShaderDataType::Mat3:
  75. return 3*3;
  76. break;
  77. case YOTO::ShaderDataType::Mat4:
  78. return 4*4;
  79. break;
  80. case YOTO::ShaderDataType::Int:
  81. return 1;
  82. break;
  83. case YOTO::ShaderDataType::Int2:
  84. return 2;
  85. break;
  86. case YOTO::ShaderDataType::Int3:
  87. return 3;
  88. break;
  89. case YOTO::ShaderDataType::Int4:
  90. return 4;
  91. break;
  92. case YOTO::ShaderDataType::Bool:
  93. return 1;
  94. break;
  95. default:
  96. break;
  97. }
  98. YT_CORE_ASSERT(false, "未知的ShaderDataType!");
  99. return 0;
  100. }
  101. };
  102. class BufferLayout {
  103. public:
  104. BufferLayout(){}
  105. BufferLayout(const std::initializer_list<BufferElement>elements)
  106. :m_Elements(elements)
  107. {
  108. CalculateOffsetAndStride();
  109. }
  110. inline uint32_t GetStride()const { return m_Stride; }
  111. inline const std::vector<BufferElement>& GetElements()const {
  112. return m_Elements;
  113. }
  114. std::vector<BufferElement>::iterator begin() { return m_Elements.begin(); }
  115. std::vector<BufferElement>::iterator end() { return m_Elements.end(); }
  116. std::vector<BufferElement>::const_iterator begin() const { return m_Elements.begin(); }
  117. std::vector<BufferElement>::const_iterator end() const { return m_Elements.end(); }
  118. private:
  119. void CalculateOffsetAndStride() {
  120. uint32_t offset = 0;
  121. m_Stride = 0;
  122. for (auto& element : m_Elements) {
  123. element.Offset = offset;
  124. offset += element.Size;
  125. m_Stride += element.Size;
  126. }
  127. }
  128. private:
  129. std::vector<BufferElement> m_Elements;
  130. uint32_t m_Stride = 0;
  131. };
  132. class VertexBuffer {
  133. public:
  134. virtual~VertexBuffer() {}
  135. virtual void Bind() const = 0;
  136. virtual void UnBind() const = 0;
  137. virtual void SetData(const void* data, uint32_t size) = 0;
  138. virtual void SetLayout(const BufferLayout& layout) = 0;
  139. virtual const BufferLayout& GetLayout()const = 0;
  140. static Ref<VertexBuffer> Create(float* vertices, uint32_t size);
  141. static Ref<VertexBuffer> Create(uint32_t size);
  142. };
  143. /// <summary>
  144. /// 目前索引仅支持32位的索引缓冲区
  145. /// </summary>
  146. class IndexBuffer {
  147. public:
  148. virtual~IndexBuffer(){}
  149. virtual void Bind() const = 0;
  150. virtual void UnBind() const = 0;
  151. virtual uint32_t GetCount() const = 0;
  152. static Ref<IndexBuffer> Create(uint32_t* indices, uint32_t count);
  153. };
  154. }

Buffer.cpp:

  1. #include"ytpch.h"
  2. #include"Buffer.h"
  3. #include "Renderer.h"
  4. #include "Platform/OpenGL/OpenGLBuffer.h"
  5. namespace YOTO {
  6. Ref<VertexBuffer> VertexBuffer::Create(uint32_t size)
  7. {
  8. switch (Renderer::GetAPI())
  9. {
  10. case RendererAPI::API::None:
  11. YT_CORE_ASSERT(false, "Buffer:API为None不支持");
  12. return nullptr;
  13. case RendererAPI::API::OpenGL:
  14. return std::make_shared<OpenGLVertexBuffer>(size);
  15. }
  16. YT_CORE_ASSERT(false, "Buffer:未知API");
  17. return nullptr;
  18. }
  19. Ref<VertexBuffer> VertexBuffer::Create(float* vertices, uint32_t size)
  20. {
  21. switch (Renderer::GetAPI())
  22. {
  23. case RendererAPI::API::None:
  24. YT_CORE_ASSERT(false,"Buffer:API为None不支持");
  25. return nullptr;
  26. case RendererAPI::API::OpenGL:
  27. return std::make_shared<OpenGLVertexBuffer>(vertices,size);
  28. }
  29. YT_CORE_ASSERT(false,"Buffer:未知API");
  30. return nullptr;
  31. }
  32. Ref<IndexBuffer> IndexBuffer::Create(uint32_t* indices, uint32_t count)
  33. {
  34. switch (Renderer::GetAPI())
  35. {
  36. case RendererAPI::API::None:
  37. YT_CORE_ASSERT(false, "Buffer:API为None不支持");
  38. return nullptr;
  39. case RendererAPI::API::OpenGL:
  40. return std::make_shared < OpenGLIndexBuffer>(indices, count);
  41. }
  42. YT_CORE_ASSERT(false, "Buffer:未知API");
  43. return nullptr;
  44. }
  45. }

OpenGLBuffer.cpp: 实现继承自Buffer的方法

  1. #include"ytpch.h"
  2. #include"OpenGLBuffer.h"
  3. #include <glad/glad.h>
  4. namespace YOTO {
  5. // VertexBuffer
  6. OpenGLVertexBuffer::OpenGLVertexBuffer(uint32_t size)
  7. {
  8. YT_PROFILE_FUNCTION();
  9. glCreateBuffers(1, &m_RendererID);
  10. glBindBuffer(GL_ARRAY_BUFFER, m_RendererID);
  11. glBufferData(GL_ARRAY_BUFFER, size, nullptr, GL_DYNAMIC_DRAW);
  12. }
  13. OpenGLVertexBuffer::OpenGLVertexBuffer(float* vertices, uint32_t size)
  14. {
  15. YT_PROFILE_FUNCTION();
  16. glCreateBuffers(1, &m_RendererID);
  17. glBindBuffer(GL_ARRAY_BUFFER, m_RendererID);
  18. glBufferData(GL_ARRAY_BUFFER, size, vertices, GL_STATIC_DRAW);
  19. }
  20. OpenGLVertexBuffer::~OpenGLVertexBuffer()
  21. {
  22. YT_PROFILE_FUNCTION();
  23. glDeleteBuffers(1, &m_RendererID);
  24. }
  25. void OpenGLVertexBuffer::Bind() const
  26. {
  27. YT_PROFILE_FUNCTION();
  28. glBindBuffer(GL_ARRAY_BUFFER, m_RendererID);
  29. }
  30. void OpenGLVertexBuffer::UnBind() const
  31. {
  32. glBindBuffer(GL_ARRAY_BUFFER, 0);
  33. }
  34. void OpenGLVertexBuffer::SetData(const void* data, uint32_t size)
  35. {
  36. glBindBuffer(GL_ARRAY_BUFFER, m_RendererID);
  37. // 用来更新一个已有缓冲区对象中的一部分数据,
  38. //data:一个指向新数据源的指针,将新的数据源拷贝到缓冲区对象中完成更新
  39. glBufferSubData(GL_ARRAY_BUFFER,0,size,data);
  40. }
  41. // IndexBuffer /
  42. OpenGLIndexBuffer::OpenGLIndexBuffer(uint32_t* indices, uint32_t count)
  43. :m_Count(count)
  44. {
  45. YT_PROFILE_FUNCTION();
  46. glCreateBuffers(1, &m_RendererID);
  47. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_RendererID);
  48. glBufferData(GL_ELEMENT_ARRAY_BUFFER, count*sizeof(uint32_t), indices, GL_STATIC_DRAW);
  49. }
  50. OpenGLIndexBuffer::~OpenGLIndexBuffer()
  51. {
  52. YT_PROFILE_FUNCTION();
  53. glDeleteBuffers(1, &m_RendererID);
  54. }
  55. void OpenGLIndexBuffer::Bind() const
  56. {
  57. YT_PROFILE_FUNCTION();
  58. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_RendererID);
  59. }
  60. void OpenGLIndexBuffer::UnBind() const
  61. {
  62. YT_PROFILE_FUNCTION();
  63. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
  64. }
  65. }

RenderAPI.h:创建DrawIndexed方法根据索引绘制图像

  1. #pragma once
  2. #include<glm/glm.hpp>
  3. #include "VertexArray.h"
  4. namespace YOTO {
  5. class RendererAPI
  6. {
  7. public:
  8. enum class API {
  9. None = 0,
  10. OpenGL = 1
  11. };
  12. public:
  13. virtual void Init() = 0;
  14. virtual void SetClearColor(const glm::vec4& color)=0;
  15. virtual void SetViewport(uint32_t x, uint32_t y, uint32_t width, uint32_t height) = 0;
  16. virtual void Clear() = 0;
  17. virtual void DrawIndexed(const Ref<VertexArray>& vertexArray,uint32_t indexCount = 0)=0;
  18. inline static API GetAPI() { return s_API; }
  19. private:
  20. static API s_API;
  21. };
  22. }

OpenGLRendererAPI.cpp: 

  1. #include "ytpch.h"
  2. #include "OpenGLRendererAPI.h"
  3. #include <glad/glad.h>
  4. namespace YOTO {
  5. void OpenGLRendererAPI::Init()
  6. {
  7. YT_PROFILE_FUNCTION();
  8. //启用混合
  9. glEnable(GL_BLEND);
  10. //设置混合函数
  11. glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
  12. //深度测试
  13. glEnable(GL_DEPTH_TEST);
  14. }
  15. void OpenGLRendererAPI::SetViewport(uint32_t x, uint32_t y, uint32_t width, uint32_t height)
  16. {
  17. glViewport(x, y, width, height);
  18. }
  19. void OpenGLRendererAPI::SetClearColor(const glm::vec4& color)
  20. {
  21. glClearColor(color.r, color.g, color.b, color.a);
  22. }
  23. void OpenGLRendererAPI::Clear()
  24. {
  25. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  26. }
  27. void OpenGLRendererAPI::DrawIndexed(const Ref<VertexArray>& vertexArray, uint32_t indexCount)
  28. {
  29. uint32_t count = indexCount ? vertexArray->GetIndexBuffer()->GetCount() : indexCount;
  30. glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_INT, nullptr);
  31. glBindTexture(GL_TEXTURE_2D, 0);
  32. }
  33. }

RenderCommand.h: 对API的DrawIndexed封装:

  1. #pragma once
  2. #include"RendererAPI.h"
  3. namespace YOTO {
  4. class RenderCommand
  5. {
  6. public:
  7. inline static void Init() {
  8. s_RendererAPI->Init();
  9. }
  10. inline static void SetViewport(uint32_t x, uint32_t y, uint32_t width, uint32_t height) {
  11. s_RendererAPI->SetViewport(x,y,width,height);
  12. }
  13. inline static void SetClearColor(const glm::vec4& color) {
  14. s_RendererAPI->SetClearColor(color);
  15. }
  16. inline static void Clear() {
  17. s_RendererAPI->Clear();
  18. }
  19. inline static void DrawIndexed(const Ref<VertexArray>& vertexArray,uint32_t count=0) {
  20. s_RendererAPI->DrawIndexed(vertexArray, count);
  21. }
  22. private:
  23. static RendererAPI* s_RendererAPI;
  24. };
  25. }

 调用:

Texture.glsl:先改下shader

  1. #type vertex
  2. #version 330 core
  3. layout(location = 0) in vec3 a_Position;
  4. layout(location = 1) in vec4 a_Color;
  5. layout(location = 2) in vec2 a_TexCoord;
  6. uniform mat4 u_ViewProjection;
  7. // uniform mat4 u_Transform;
  8. out vec4 v_Color;
  9. out vec2 v_TexCoord;
  10. void main() {
  11. v_Color = a_Color;
  12. v_TexCoord = a_TexCoord;
  13. // 由规则动态生成的顶点位置(基于本地空间)没有涉及transform变换顶点位置
  14. // gl_Position = u_ViewProjection * u_Transform * vec4(a_Position, 1.0);
  15. gl_Position = u_ViewProjection * vec4(a_Position, 1.0);
  16. }
  17. #type fragment
  18. #version 330 core
  19. layout(location = 0) out vec4 color;
  20. in vec4 v_Color;
  21. in vec2 v_TexCoord;
  22. uniform vec4 u_Color;
  23. uniform float u_TilingFactor;
  24. uniform sampler2D u_Texture;
  25. void main() {
  26. color = v_Color;
  27. }

Sandbox2D.cpp:

  1. #include "Sandbox2D.h"
  2. #include <imgui/imgui.h>
  3. #include <glm/gtc/matrix_transform.hpp>
  4. //#include <Platform/OpenGL/OpenGLShader.h>
  5. #include <glm/gtc/type_ptr.hpp>
  6. #include<vector>
  7. #include<chrono>
  8. template<typename Fn>
  9. class Timer {
  10. public:
  11. Timer(const char* name, Fn&&func)
  12. :m_Name(name),m_Func(func),m_Stopped(false)
  13. {
  14. m_StartTimepoint = std::chrono::high_resolution_clock::now();
  15. }
  16. ~Timer() {
  17. if (!m_Stopped) {
  18. Stop();
  19. }
  20. }
  21. void Stop() {
  22. auto endTimepoint= std::chrono::high_resolution_clock::now();
  23. long long start = std::chrono::time_point_cast<std::chrono::microseconds>(m_StartTimepoint).time_since_epoch().count();
  24. long long end = std::chrono::time_point_cast<std::chrono::microseconds>(endTimepoint).time_since_epoch().count();
  25. m_Stopped = true;
  26. float duration = (end - start)*0.001f;
  27. m_Func({m_Name,duration});
  28. //std::cout << "Timer:"<< m_Name << "时差:" << duration << "ms" << std::endl;
  29. }
  30. private:
  31. const char* m_Name;
  32. std::chrono::time_point<std::chrono::steady_clock>m_StartTimepoint;
  33. bool m_Stopped;
  34. Fn m_Func;
  35. };
  36. //未找到匹配的重载:auto的问题,改回原来的类型就好了
  37. #define PROFILE_SCOPE(name) Timer timer##__LINE__(name,[&](ProfileResult profileResult) {m_ProfileResults.push_back(profileResult);})
  38. Sandbox2D::Sandbox2D()
  39. :Layer("Sandbox2D"), m_CameraController(1280.0f / 720.0f, true)
  40. {
  41. }
  42. void Sandbox2D::OnAttach()
  43. {
  44. YT_PROFILE_FUNCTION();
  45. m_CheckerboardTexture = YOTO::Texture2D::Create("assets/textures/Checkerboard.png");
  46. }
  47. void Sandbox2D::OnDetach()
  48. {
  49. YT_PROFILE_FUNCTION();
  50. }
  51. void Sandbox2D::OnUpdate(YOTO::Timestep ts)
  52. {
  53. YT_PROFILE_FUNCTION();
  54. //update
  55. m_CameraController.OnUpdate(ts);
  56. {
  57. YT_PROFILE_SCOPE("Sandbox2D::Renderer Prep");
  58. //Render
  59. YOTO::RenderCommand::SetClearColor({ 0.2f, 0.2f, 0.2f, 1.0f });
  60. YOTO::RenderCommand::Clear();
  61. }
  62. {
  63. YT_PROFILE_SCOPE("Sandbox2D::Renderer Draw");
  64. YOTO::Renderer2D::BeginScene(m_CameraController.GetCamera());
  65. {
  66. /* static glm::mat4 scale = glm::scale(glm::mat4(1.0f), glm::vec3(0.1f));
  67. glm::vec4 redColor(0.8f, 0.3f, 0.3f, 1.0f);
  68. glm::vec4 blueColor(0.2f, 0.3f, 0.8f, 1.0f);*/
  69. /*std::dynamic_pointer_cast<YOTO::OpenGLShader>(m_FlatColorShader)->Bind();
  70. std::dynamic_pointer_cast<YOTO::OpenGLShader>(m_FlatColorShader)->UploadUniformFloat4("u_Color", m_SquareColor);
  71. YOTO::Renderer::Submit(m_FlatColorShader, m_SquareVA, glm::scale(glm::mat4(1.0f), glm::vec3(1.5f)));*/
  72. // YOTO::Renderer2D::DrawRotatedQuad({ -1.0f,0.0f }, { 0.8f,0.8f }, glm::radians(45.0f),{ 0.8f,0.2f,0.3f,1.0f });
  73. YOTO::Renderer2D::DrawQuad({ -1.0f,0.0f }, { 0.8f,0.8f }, { 0.8f,0.2f,0.3f,1.0f });
  74. YOTO::Renderer2D::DrawQuad({ 0.5f,-0.5f }, { 0.5f,0.75f }, { 0.2f,0.3f,0.8f,1.0f });
  75. //YOTO::Renderer2D::DrawQuad({ 0.0f,0.0f,-0.1f }, { 10.0f,10.0f }, m_CheckerboardTexture,10.0f,glm::vec4(1.0f,0.9f,0.9f,1.0f));
  76. YOTO::Renderer2D::EndScene();
  77. }
  78. }
  79. }
  80. void Sandbox2D::OnImGuiRender()
  81. {
  82. YT_PROFILE_FUNCTION();
  83. ImGui::Begin("Setting");
  84. ImGui::ColorEdit4("Color", glm::value_ptr(m_SquareColor));
  85. for (auto& res : m_ProfileResults) {
  86. char lable[50];
  87. strcpy(lable, "%.3fms ");
  88. strcat(lable, res.Name);
  89. ImGui::Text(lable, res.Time);
  90. }
  91. m_ProfileResults.clear();
  92. ImGui::End();
  93. }
  94. void Sandbox2D::OnEvent(YOTO::Event& e)
  95. {
  96. YT_PROFILE_FUNCTION();
  97. m_CameraController.OnEvent(e);
  98. }

cool! 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/341495
推荐阅读
  

闽ICP备14008679号