• 跟着cherno手搓游戏引擎【25】封装2DRenderer,封装shader传参,自定义Texture


    封装2DRenderer:

    Renderer.h:

    1. #include"ytpch.h"
    2. #include"Renderer.h"
    3. #include
    4. #include"Renderer2D.h"
    5. namespace YOTO {
    6. Renderer::SceneData* Renderer::m_SceneData = new Renderer::SceneData;
    7. void Renderer::Init()
    8. {
    9. RenderCommand::Init();
    10. Renderer2D::Init();
    11. }
    12. void Renderer::OnWindowResize(uint32_t width, uint32_t height)
    13. {
    14. RenderCommand::SetViewport(0, 0, width, height);
    15. }
    16. void Renderer::BeginScene(OrthographicCamera& camera)
    17. {
    18. m_SceneData->ViewProjectionMatrix = camera.GetViewProjectionMatrix();
    19. }
    20. void Renderer::EndScene()
    21. {
    22. }
    23. void Renderer::Submit(const Ref& shader, const Ref& vertexArray, const glm::mat4& transform)
    24. {
    25. shader->Bind();
    26. std::dynamic_pointer_cast(shader)->UploadUniformMat4("u_ViewProjection", m_SceneData->ViewProjectionMatrix);
    27. std::dynamic_pointer_cast(shader)->UploadUniformMat4("u_Transform", transform);
    28. /* mi.Bind();*/
    29. vertexArray->Bind();
    30. RenderCommand::DrawIndexed(vertexArray);
    31. }
    32. }

    Renderer2D.h:专门渲染2D的类,负责“画什么”的问题

    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 DrawQuad(const glm::vec2& position, const glm::vec2& size, const glm::vec4& color);
    14. static void DrawQuad(const glm::vec3& position, const glm::vec2& size, const glm::vec4& color);
    15. static void DrawQuad(const glm::vec2& position, const glm::vec2& size, const Ref texture);
    16. static void DrawQuad(const glm::vec3& position, const glm::vec2& size, const Ref texture);
    17. private:
    18. private:
    19. };
    20. }

     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
    7. #include "RenderCommand.h"
    8. namespace YOTO {
    9. struct Renderer2DStorage {
    10. Ref QuadVertexArray;
    11. //Ref FlatColorShader;
    12. Ref TextureShader;
    13. Ref WhiteTexture;
    14. };
    15. static Renderer2DStorage* s_Data;
    16. void Renderer2D::Init()
    17. {
    18. s_Data = new Renderer2DStorage();
    19. s_Data->QuadVertexArray = VertexArray::Create();
    20. float squareVertices[5 * 4] = {
    21. -0.5f,-0.5f,0.0f,0.0f,0.0f,
    22. 0.5f,-0.5f,0.0f,1.0f,0.0f,
    23. 0.5f,0.5f,0.0f,1.0f,1.0f,
    24. -0.5f,0.5f,0.0f,0.0f,1.0f,
    25. };
    26. Ref squareVB;
    27. squareVB.reset(VertexBuffer::Create(squareVertices, sizeof(squareVertices)));
    28. squareVB->SetLayout({
    29. {ShaderDataType::Float3,"a_Position"},
    30. {ShaderDataType::Float2,"a_TexCoord"}
    31. });
    32. s_Data->QuadVertexArray->AddVertexBuffer(squareVB);
    33. uint32_t squareIndices[6] = { 0,1,2,2,3,0 };
    34. Ref squareIB;
    35. squareIB.reset((IndexBuffer::Create(squareIndices, sizeof(squareIndices) / sizeof(uint32_t))));
    36. s_Data->QuadVertexArray->AddIndexBuffer(squareIB);
    37. s_Data->WhiteTexture = Texture2D::Create(1, 1);
    38. uint32_t whiteTextureData = 0xffffffff;
    39. s_Data->WhiteTexture->SetData(&whiteTextureData,sizeof(uint32_t));
    40. //s_Data->FlatColorShader =Shader::Create("assets/shaders/FlatColor.glsl");
    41. s_Data->TextureShader= Shader::Create("assets/shaders/Texture.glsl");
    42. s_Data->TextureShader->Bind();
    43. s_Data->TextureShader->SetInt("u_Texture", 0);
    44. }
    45. void Renderer2D::ShutDown()
    46. {
    47. delete s_Data;
    48. }
    49. void Renderer2D::BeginScene(const OrthographicCamera& camera)
    50. {
    51. /*s_Data->FlatColorShader->Bind();
    52. s_Data->FlatColorShader->SetMat4("u_ViewProjection",camera.GetViewProjectionMatrix());*/
    53. s_Data->TextureShader->Bind();
    54. s_Data->TextureShader->SetMat4("u_ViewProjection", camera.GetViewProjectionMatrix());
    55. }
    56. void Renderer2D::EndScene()
    57. {
    58. }
    59. void Renderer2D::DrawQuad(const glm::vec2& position, const glm::vec2& size, const glm::vec4& color)
    60. {
    61. DrawQuad({ position.x,position.y,0.0f }, size, color);
    62. }
    63. void Renderer2D::DrawQuad(const glm::vec3& position, const glm::vec2& size, const glm::vec4& color)
    64. {
    65. //s_Data->FlatColorShader->Bind();
    66. //s_Data->FlatColorShader->SetFloat4("u_Color", color);
    67. //s_Data->TextureShader->Bind();
    68. s_Data->TextureShader->SetFloat4("u_Color", color);
    69. s_Data->WhiteTexture->Bind();
    70. glm::mat4 transform = glm::translate(glm::mat4(1.0f), position) /**rotation*/ * glm::scale(glm::mat4(1.0f), {size.x,size.y,1.0f});
    71. s_Data->TextureShader->SetMat4("u_Transform", transform);
    72. s_Data->QuadVertexArray->Bind();
    73. RenderCommand::DrawIndexed(s_Data->QuadVertexArray);
    74. }
    75. void Renderer2D::DrawQuad(const glm::vec2& position, const glm::vec2& size, const Ref texture)
    76. {
    77. DrawQuad({ position.x,position.y,0.0f }, size, texture);
    78. }
    79. void Renderer2D::DrawQuad(const glm::vec3& position, const glm::vec2& size, const Ref texture)
    80. {
    81. //s_Data->TextureShader->Bind();
    82. s_Data->TextureShader->SetFloat4("u_Color", {0.2f,0.3f,0.8f,0.5f});
    83. texture->Bind();
    84. glm::mat4 transform = glm::translate(glm::mat4(1.0f), position) /**rotation*/ * glm::scale(glm::mat4(1.0f), { size.x,size.y,1.0f });
    85. s_Data->TextureShader->SetMat4("u_Transform", transform);
    86. s_Data->QuadVertexArray->Bind();
    87. RenderCommand::DrawIndexed(s_Data->QuadVertexArray);
    88. }
    89. }

    封装Shader传参:

    Shader.h:添加SetInt、SetFloat3...等等Set方法

    1. #pragma once
    2. #include
    3. #include
    4. namespace YOTO {
    5. class Shader {
    6. public:
    7. virtual~Shader()=default;
    8. virtual void Bind()const=0;
    9. virtual void UnBind()const=0;
    10. virtual void SetInt(const std::string& name,int value) = 0;
    11. virtual void SetFloat3(const std::string& name, const glm::vec3& value) = 0;
    12. virtual void SetFloat4(const std::string& name, const glm::vec4& value) = 0;
    13. virtual void SetMat4(const std::string& name, const glm::mat4& value) = 0;
    14. virtual const std::string& GetName()const = 0;
    15. static Ref Create(const std::string& filepath);
    16. static Ref Create(const std::string&name, const std::string& vertexSrc, const std::string& fragmentSrc);
    17. };
    18. class ShaderLibrary {
    19. public:
    20. void Add(const Ref& shader);
    21. void Add(const std::string &name,const Ref& shader);
    22. Ref Load(const std::string filepath);
    23. Ref Load(const std::string &name,const std::string filepath);
    24. Ref Get(const std::string& name);
    25. bool Exists(const std::string& name);
    26. private:
    27. std::unordered_map> m_Shaders;
    28. };
    29. }

    OpenGLShader.h:同Shader.h

    1. #pragma once
    2. #include
    3. #include "YOTO/Renderer/Shader.h"
    4. #include
    5. typedef unsigned int GLenum;
    6. namespace YOTO {
    7. class OpenGLShader:public Shader {
    8. public:
    9. OpenGLShader(const std::string& filepath);
    10. OpenGLShader(const std::string &name,const std::string& vertexSrc, const std::string& fragmentSrc);
    11. ~OpenGLShader();
    12. void Bind()const override;
    13. void UnBind()const override;
    14. virtual void SetInt(const std::string& name, int value) override;
    15. virtual void SetFloat3(const std::string& name, const glm::vec3& value) override;
    16. virtual void SetFloat4(const std::string& name, const glm::vec4& value)override;
    17. virtual void SetMat4(const std::string& name, const glm::mat4& value) override;
    18. virtual const std::string& GetName()const override { return m_Name; }
    19. void UploadUniformMat4(const std::string& name, const glm::mat4& matrix);
    20. void UploadUniformMat3(const std::string& name, const glm::mat3& matrix);
    21. void UploadUniformFloat4(const std::string& name, const glm::vec4& values);
    22. void UploadUniformFloat3(const std::string& name, const glm::vec3& values);
    23. void UploadUniformFloat2(const std::string& name, const glm::vec2& values);
    24. void UploadUniformFloat(const std::string& name, float values);
    25. void UploadUniformInt(const std::string& name, int values);
    26. private:
    27. std::string ReadFile(const std::string filepath);
    28. std::unordered_map PreProcess(const std::string& source);
    29. void Compile(const std::unordered_map& shaderSources);
    30. private:
    31. uint32_t m_RendererID;
    32. std::string m_Name;
    33. }
    34. ;
    35. }

    OpenGLShader.cpp: 

    1. #include "ytpch.h"
    2. #include "OpenGLShader.h"
    3. #include
    4. #include
    5. namespace YOTO {
    6. static GLenum ShaderTypeFromString(const std::string& type) {
    7. if (type == "vertex") {
    8. return GL_VERTEX_SHADER;
    9. }
    10. if (type == "fragment" || type == "pixel") {
    11. return GL_FRAGMENT_SHADER;
    12. }
    13. YT_CORE_ASSERT(false, "不知道的shader类型");
    14. return 0;
    15. }
    16. OpenGLShader::OpenGLShader(const std::string& filepath)
    17. {
    18. std::string source = ReadFile(filepath);
    19. YT_CORE_ASSERT(source.size(), "GLSL读取的字符串为空");
    20. auto shaderSources = PreProcess(source);
    21. Compile(shaderSources);
    22. auto lastSlash = filepath.find_last_of("/\\");
    23. lastSlash = lastSlash == std::string::npos ? 0 : lastSlash + 1;
    24. auto lastDot = filepath.rfind('.');
    25. auto count = lastDot == std::string::npos ? filepath.size() - lastSlash : lastDot - lastSlash;
    26. m_Name=filepath.substr(lastSlash, count);
    27. }
    28. OpenGLShader::OpenGLShader(const std::string& name, const std::string& vertexSrc, const std::string& fragmentSrc)
    29. :m_Name(name){
    30. std::unordered_mapsources;
    31. sources[GL_VERTEX_SHADER] = vertexSrc;
    32. sources[GL_FRAGMENT_SHADER] = fragmentSrc;
    33. Compile(sources);
    34. }
    35. OpenGLShader::~OpenGLShader()
    36. {
    37. glDeleteProgram(m_RendererID);
    38. }
    39. std::string OpenGLShader::ReadFile(const std::string filepath)
    40. {
    41. std::string result;
    42. std::ifstream in(filepath, std::ios::in | std::ios::binary);
    43. if (in) {
    44. in.seekg(0, std::ios::end); // 将指针放在最后面
    45. result.resize(in.tellg()); // 初始化string的大小, in.tellg()返回位置
    46. in.seekg(0, std::ios::beg); // in指回头部
    47. in.read(&result[0], result.size()); // in读入放在result指向的内存中
    48. }
    49. else {
    50. YT_CORE_ERROR("不能打开文件:{0}", filepath);
    51. }
    52. return result;
    53. }
    54. std::unordered_map OpenGLShader::PreProcess(const std::string& source)
    55. {
    56. std::unordered_map shaderSources;
    57. std::string typeToken = "#type";
    58. size_t typeTokenLen = typeToken.size();
    59. size_t findCurPos = source.find(typeToken, 0);
    60. size_t findNextPos = findCurPos;
    61. while (findNextPos != std::string::npos) {
    62. size_t curlineEndPos = source.find_first_of("\r\n", findCurPos);///r/n写错为/r/n
    63. YT_CORE_ASSERT(curlineEndPos != std::string::npos, "解析shader失败");
    64. size_t begin = findCurPos + typeTokenLen + 1;
    65. std::string type = source.substr(begin, curlineEndPos - begin);// 获取到是vertex还是fragment
    66. YT_CORE_ASSERT(ShaderTypeFromString(type), "无效的shader的类型 ");
    67. size_t nextLinePos = source.find_first_not_of("\r\n", curlineEndPos);
    68. findNextPos = source.find(typeToken, nextLinePos);
    69. // 获取到具体的shader代码
    70. shaderSources[ShaderTypeFromString(type)] = source.substr(nextLinePos, findNextPos - (nextLinePos == std::string::npos ? source.size() - 1 : nextLinePos));
    71. findCurPos = findNextPos;
    72. }
    73. return shaderSources;
    74. /*
    75. 用find,而不是find_firtst_of,因为
    76. find返回完全匹配的字符串的的位置;
    77. find_first_of返回被查匹配字符串中某个字符的第一次出现位置。
    78. std::string::npos是一个非常大的数
    79. source.substr(0, source.size() + 10000)截取到从头到末尾,不会报错
    80. */
    81. }
    82. void OpenGLShader::Compile(const std::unordered_map& shaderSources)
    83. {
    84. GLuint program = glCreateProgram();
    85. YT_CORE_ASSERT(shaderSources.size()<=2,"OpenGLShader:shader只支持两种!")
    86. std::arrayglShaderIDs;
    87. int glShaderIDIndex=0;
    88. for (auto& kv : shaderSources) {
    89. GLenum type = kv.first;
    90. const std::string& source = kv.second;
    91. // Create an empty vertex shader handle
    92. GLuint shader = glCreateShader(type);
    93. // Send the vertex shader source code to GL
    94. // Note that std::string's .c_str is NULL character terminated.
    95. const GLchar* sourceCStr = source.c_str();
    96. glShaderSource(shader, 1, &sourceCStr, 0);
    97. // Compile the vertex shader
    98. glCompileShader(shader);
    99. GLint isCompiled = 0;
    100. glGetShaderiv(shader, GL_COMPILE_STATUS, &isCompiled);
    101. if (isCompiled == GL_FALSE)
    102. {
    103. GLint maxLength = 0;
    104. glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &maxLength);
    105. // The maxLength includes the NULL character
    106. std::vector infoLog(maxLength);
    107. glGetShaderInfoLog(shader, maxLength, &maxLength, &infoLog[0]);
    108. // We don't need the shader anymore.
    109. glDeleteShader(shader);
    110. // Use the infoLog as you see fit.
    111. // In this simple program, we'll just leave
    112. YT_CORE_ERROR("{0} ", infoLog.data());
    113. YT_CORE_ASSERT(false, "shader 编译失败!");
    114. break;
    115. }
    116. // Attach our shaders to our program
    117. glAttachShader(program, shader);
    118. glShaderIDs[glShaderIDIndex++]=shader;
    119. }
    120. // Link our program
    121. glLinkProgram(program);
    122. // Note the different functions here: glGetProgram* instead of glGetShader*.
    123. GLint isLinked = 0;
    124. glGetProgramiv(program, GL_LINK_STATUS, (int*)&isLinked);
    125. if (isLinked == GL_FALSE)
    126. {
    127. GLint maxLength = 0;
    128. glGetProgramiv(program, GL_INFO_LOG_LENGTH, &maxLength);
    129. // The maxLength includes the NULL character
    130. std::vector infoLog(maxLength);
    131. glGetProgramInfoLog(program, maxLength, &maxLength, &infoLog[0]);
    132. // We don't need the program anymore.
    133. glDeleteProgram(program);
    134. // Don't leak shaders either.
    135. for (auto id : glShaderIDs) {
    136. glDeleteShader(id);
    137. }
    138. // Use the infoLog as you see fit.
    139. // In this simple program, we'll just leave
    140. YT_CORE_ERROR("{0} ", infoLog.data());
    141. YT_CORE_ASSERT(false, "shader link failure!");
    142. return;
    143. }
    144. // Always detach shaders after a successful link.
    145. for (auto id : glShaderIDs) {
    146. glDetachShader(program, id);
    147. }
    148. m_RendererID = program;
    149. }
    150. void OpenGLShader::Bind() const
    151. {
    152. glUseProgram(m_RendererID);
    153. }
    154. void OpenGLShader::UnBind() const
    155. {
    156. glUseProgram(0);
    157. }
    158. void OpenGLShader::SetInt(const std::string& name, int value)
    159. {
    160. UploadUniformInt(name, value);
    161. }
    162. void OpenGLShader::SetFloat3(const std::string& name, const glm::vec3& value)
    163. {
    164. UploadUniformFloat3(name, value);
    165. }
    166. void OpenGLShader::SetFloat4(const std::string& name, const glm::vec4& value)
    167. {
    168. UploadUniformFloat4(name, value);
    169. }
    170. void OpenGLShader::SetMat4(const std::string& name, const glm::mat4& value)
    171. {
    172. UploadUniformMat4(name, value);
    173. }
    174. void OpenGLShader::UploadUniformMat4(const std::string& name, const glm::mat4& matrix)
    175. {
    176. GLint loacation = glGetUniformLocation(m_RendererID, name.c_str());
    177. glUniformMatrix4fv(loacation, 1, GL_FALSE, glm::value_ptr(matrix));
    178. }
    179. void OpenGLShader::UploadUniformMat3(const std::string& name, const glm::mat3& matrix)
    180. {
    181. GLint loacation = glGetUniformLocation(m_RendererID, name.c_str());
    182. glUniformMatrix3fv(loacation, 1, GL_FALSE, glm::value_ptr(matrix));
    183. }
    184. void OpenGLShader::UploadUniformFloat4(const std::string& name, const glm::vec4& values)
    185. {
    186. GLint loacation = glGetUniformLocation(m_RendererID, name.c_str());
    187. glUniform4f(loacation, values.x, values.y, values.z, values.w);
    188. }
    189. void OpenGLShader::UploadUniformFloat3(const std::string& name, const glm::vec3& values)
    190. {
    191. GLint loacation = glGetUniformLocation(m_RendererID, name.c_str());
    192. glUniform3f(loacation, values.x, values.y, values.z);
    193. }
    194. void OpenGLShader::UploadUniformFloat2(const std::string& name, const glm::vec2& values)
    195. {
    196. GLint loacation = glGetUniformLocation(m_RendererID, name.c_str());
    197. glUniform2f(loacation, values.x, values.y);
    198. }
    199. void OpenGLShader::UploadUniformFloat(const std::string& name, float values)
    200. {
    201. GLint loacation = glGetUniformLocation(m_RendererID, name.c_str());
    202. glUniform1f(loacation, values);
    203. }
    204. void OpenGLShader::UploadUniformInt(const std::string& name, int values)
    205. {
    206. GLint loacation = glGetUniformLocation(m_RendererID, name.c_str());
    207. glUniform1i(loacation, values);
    208. }
    209. }

    添加自定义Texture方法:

    Texture.h:添加新的Create方法:根据宽高添加

    1. #pragma once
    2. namespace YOTO {
    3. class Texture
    4. {
    5. public:
    6. virtual ~Texture() = default;
    7. virtual uint32_t GetWidth()const = 0;
    8. virtual uint32_t GetHeight()const = 0;
    9. virtual void SetData(void* data, uint32_t size) = 0;
    10. virtual void Bind(uint32_t slot=0)const = 0;
    11. };
    12. class Texture2D :public Texture
    13. {
    14. public:
    15. static RefCreate(uint32_t width,uint32_t height);
    16. static RefCreate(const std::string& path);
    17. };
    18. }

    Texture.cpp: 

    1. #include "ytpch.h"
    2. #include "Texture.h"
    3. #include"Renderer.h"
    4. #include "Platform/OpenGL/OpenGLTexture.h"
    5. namespace YOTO {
    6. Ref Texture2D::Create(uint32_t width, uint32_t height)
    7. {
    8. switch (Renderer::GetAPI())
    9. {
    10. case RendererAPI::API::None:
    11. YT_CORE_ASSERT(false, "Texture2D:API为None不支持");
    12. return nullptr;
    13. case RendererAPI::API::OpenGL:
    14. return CreateRef(width,height);
    15. }
    16. YT_CORE_ASSERT(false, "Buffer:未知API");
    17. return nullptr;
    18. }
    19. Ref Texture2D::Create(const std::string& path)
    20. {
    21. switch (Renderer::GetAPI())
    22. {
    23. case RendererAPI::API::None:
    24. YT_CORE_ASSERT(false, "Texture2D:API为None不支持");
    25. return nullptr;
    26. case RendererAPI::API::OpenGL:
    27. return CreateRef(path);
    28. }
    29. YT_CORE_ASSERT(false, "Buffer:未知API");
    30. return nullptr;
    31. }
    32. }

    OpenGLTexture.h:同Texture.h相同,且添加设置texture数据的方法SetData:

    1. #pragma once
    2. #include"YOTO/Renderer/Texture.h"
    3. #include
    4. namespace YOTO {
    5. class OpenGLTexture2D:public Texture2D
    6. {
    7. public:
    8. OpenGLTexture2D(uint32_t width,uint32_t height);
    9. OpenGLTexture2D(const std::string path);
    10. virtual~OpenGLTexture2D();
    11. virtual uint32_t GetWidth()const override { return m_Width; }
    12. virtual uint32_t GetHeight()const override { return m_Height; }
    13. virtual void SetData(void* data, uint32_t size)override;
    14. virtual void Bind(uint32_t slot=0)const override;
    15. private:
    16. std::string m_Path;
    17. uint32_t m_Width, m_Height;
    18. uint32_t m_RendererID;
    19. GLenum m_InternalFormat, m_DataFormat;
    20. };
    21. }

    OpenGLTexture.cpp: 

    1. #include "ytpch.h"
    2. #include "OpenGLTexture.h"
    3. #include
    4. #include"stb_image.h"
    5. namespace YOTO {
    6. OpenGLTexture2D::OpenGLTexture2D(uint32_t width, uint32_t height)
    7. :m_Width(width),m_Height(height)
    8. {
    9. m_InternalFormat = GL_RGBA8;
    10. m_DataFormat = GL_RGBA;
    11. glCreateTextures(GL_TEXTURE_2D, 1, &m_RendererID);
    12. ///告诉OpenGLm_RendererID的纹理存储的是rbg8位,宽高的缓冲区
    13. glTextureStorage2D(m_RendererID, 1, m_InternalFormat, m_Width, m_Height);
    14. //配置参数:纹理放大时用周围颜色的平均值过滤
    15. glTextureParameteri(m_RendererID, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    16. glTextureParameteri(m_RendererID, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    17. glTextureParameteri(m_RendererID, GL_TEXTURE_WRAP_S, GL_REPEAT);
    18. glTextureParameteri(m_RendererID, GL_TEXTURE_WRAP_T, GL_REPEAT);
    19. }
    20. OpenGLTexture2D::OpenGLTexture2D(const std::string path)
    21. :m_Path(path)
    22. {
    23. int width, height, channels;
    24. stbi_set_flip_vertically_on_load(1);//翻转
    25. stbi_uc*data=stbi_load(path.c_str(),&width,&height,&channels,0);
    26. YT_CORE_ASSERT(data, "图片加载错误");
    27. m_Width = width;
    28. m_Height = height;
    29. GLenum internalFormat = 0,dataFormat=0;
    30. if (channels == 4) {
    31. internalFormat = GL_RGBA8;
    32. dataFormat = GL_RGBA;
    33. }
    34. else if (channels==3) {
    35. internalFormat = GL_RGB8;
    36. dataFormat = GL_RGB;
    37. }
    38. m_InternalFormat = internalFormat;
    39. m_DataFormat = dataFormat;
    40. YT_CORE_ASSERT(internalFormat& dataFormat,"OpenGLTexture2D:不支持的颜色格式")
    41. //创建纹理
    42. glCreateTextures(GL_TEXTURE_2D, 1, &m_RendererID);
    43. ///告诉OpenGLm_RendererID的纹理存储的是rbg8位,宽高的缓冲区
    44. glTextureStorage2D(m_RendererID, 1, internalFormat,m_Width,m_Height);
    45. //配置参数:纹理放大时用周围颜色的平均值过滤
    46. glTextureParameteri(m_RendererID,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
    47. glTextureParameteri(m_RendererID, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    48. glTextureParameteri(m_RendererID, GL_TEXTURE_WRAP_S, GL_REPEAT);
    49. glTextureParameteri(m_RendererID, GL_TEXTURE_WRAP_T, GL_REPEAT);
    50. glTextureSubImage2D(m_RendererID, 0, 0, 0, m_Width, m_Height, dataFormat,GL_UNSIGNED_BYTE,data);
    51. stbi_image_free(data);
    52. }
    53. OpenGLTexture2D::~OpenGLTexture2D()
    54. {
    55. glDeleteTextures(1,&m_RendererID);
    56. }
    57. void OpenGLTexture2D::SetData(void* data, uint32_t size)
    58. {
    59. uint32_t bpc = m_DataFormat == GL_RGBA ? 4 : 3;
    60. YT_CORE_ASSERT(size == m_Width * m_Height * bpc,"OpenGLTexture2D:数据必须是完整的!");
    61. glTextureSubImage2D(m_RendererID, 0, 0, 0, m_Width, m_Height,m_DataFormat, GL_UNSIGNED_BYTE,data);
    62. }
    63. void OpenGLTexture2D::Bind(uint32_t slot) const
    64. {
    65. glBindTextureUnit(slot, m_RendererID);
    66. }
    67. }

    Sandbox2D.h:添加m_CheckerboardTexture

    1. #pragma once
    2. #include "YOTO.h"
    3. class Sandbox2D :public YOTO::Layer
    4. {public:
    5. Sandbox2D();
    6. virtual ~Sandbox2D() = default;
    7. virtual void OnAttach()override;
    8. virtual void OnDetach()override;
    9. void OnUpdate(YOTO::Timestep ts)override;
    10. virtual void OnImGuiRender() override;
    11. void OnEvent(YOTO::Event& e)override;
    12. private:
    13. YOTO::OrthographicCameraController m_CameraController;
    14. YOTO::Ref m_FlatColorShader;
    15. YOTO::Ref m_SquareVA;
    16. YOTO::Refm_CheckerboardTexture;
    17. glm::vec4 m_SquareColor = { 0.2f,0.3f,0.7f,1.0f };
    18. };

    化简Sandbox2D:

    Sandbox2D.cpp:把传shader参数的代码注释掉 ,统一使用DrawQuad封装;负责“怎么画”的问题:

    1. #include "Sandbox2D.h"
    2. #include
    3. #include
    4. //#include
    5. #include
    6. Sandbox2D::Sandbox2D()
    7. :Layer("Sandbox2D"), m_CameraController(1280.0f / 720.0f, true)
    8. {
    9. }
    10. void Sandbox2D::OnAttach()
    11. {
    12. m_CheckerboardTexture = YOTO::Texture2D::Create("assets/textures/Checkerboard.png");
    13. }
    14. void Sandbox2D::OnDetach()
    15. {
    16. }
    17. void Sandbox2D::OnUpdate(YOTO::Timestep ts)
    18. { //update
    19. m_CameraController.OnUpdate(ts);
    20. //Render
    21. YOTO::RenderCommand::SetClearColor({ 0.2f, 0.2f, 0.2f, 1.0f });
    22. YOTO::RenderCommand::Clear();
    23. YOTO::Renderer2D::BeginScene(m_CameraController.GetCamera());
    24. {
    25. static glm::mat4 scale = glm::scale(glm::mat4(1.0f), glm::vec3(0.1f));
    26. glm::vec4 redColor(0.8f, 0.3f, 0.3f, 1.0f);
    27. glm::vec4 blueColor(0.2f, 0.3f, 0.8f, 1.0f);
    28. /*std::dynamic_pointer_cast(m_FlatColorShader)->Bind();
    29. std::dynamic_pointer_cast(m_FlatColorShader)->UploadUniformFloat4("u_Color", m_SquareColor);
    30. YOTO::Renderer::Submit(m_FlatColorShader, m_SquareVA, glm::scale(glm::mat4(1.0f), glm::vec3(1.5f)));*/
    31. YOTO::Renderer2D::DrawQuad({ -1.0f,0.0f }, { 0.8f,0.8f }, {0.8f,0.2f,0.3f,1.0f});
    32. YOTO::Renderer2D::DrawQuad({ 0.5f,-0.5f }, { 0.5f,0.75f }, { 0.2f,0.3f,0.8f,1.0f });
    33. YOTO::Renderer2D::DrawQuad({ 0.0f,0.0f,-0.1f }, {10.0f,10.0f }, m_CheckerboardTexture);
    34. YOTO::Renderer2D::EndScene();
    35. }
    36. }
    37. void Sandbox2D::OnImGuiRender()
    38. {
    39. ImGui::Begin("设置");
    40. ImGui::ColorEdit4("正方形颜色", glm::value_ptr(m_SquareColor));
    41. ImGui::End();
    42. }
    43. void Sandbox2D::OnEvent(YOTO::Event& e)
    44. {
    45. m_CameraController.OnEvent(e);
    46. }

    小修改:

    OpenGLRendererAPI.cpp:DrawIndexed中添加解绑Texture:

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

    flatColor.glsl:

    1. #type vertex
    2. #version 330 core
    3. layout(location = 0) in vec3 a_Position;
    4. uniform mat4 u_ViewProjection;
    5. uniform mat4 u_Transform;
    6. void main(){
    7. gl_Position =u_ViewProjection*u_Transform*vec4( a_Position,1.0);
    8. }
    9. #type fragment
    10. #version 330 core
    11. layout(location = 0) out vec4 color;
    12. uniform vec4 u_Color ;
    13. void main(){
    14. color =u_Color;
    15. }

    Texture.glsl:

    1. #type vertex
    2. #version 330 core
    3. layout(location = 0) in vec3 a_Position;
    4. layout(location = 1) in vec2 a_TexCoord;
    5. uniform mat4 u_ViewProjection;
    6. uniform mat4 u_Transform;
    7. out vec2 v_TexCoord;
    8. out vec3 v_Position;
    9. void main(){
    10. v_TexCoord=a_TexCoord;
    11. v_Position=a_Position;
    12. gl_Position =u_ViewProjection*u_Transform*vec4( a_Position,1.0);
    13. }
    14. #type fragment
    15. #version 330 core
    16. layout(location = 0) out vec4 color;
    17. in vec3 v_Position;
    18. in vec2 v_TexCoord;
    19. uniform vec4 u_Color ;
    20. uniform sampler2D u_Texture ;
    21. void main(){
    22. color = texture(u_Texture, v_TexCoord*10.0f)*u_Color;
    23. }

    YOTO.h:添加:

    #include"YOTO/Renderer/Renderer2D.h"

    Core.h:

    1. #pragma once
    2. #include
    3. //用于dll的宏
    4. #ifdef YT_PLATFORM_WINDOWS
    5. #if YT_DYNAMIC_LINK
    6. #ifdef YT_BUILD_DLL
    7. #define YOTO_API __declspec(dllexport)
    8. #else
    9. #define YOTO_API __declspec(dllimport)
    10. #endif // DEBUG
    11. #else
    12. #define YOTO_API
    13. #endif
    14. #else
    15. #error YOTO_ONLY_SUPPORT_WINDOWS
    16. #endif // YOTO_PLATFORM_WINDOWS
    17. #ifdef YT_DEBUG
    18. #define YT_ENABLE_ASSERTS
    19. #endif
    20. #ifdef YT_ENABLE_ASSERTS
    21. #define YT_CLIENT_ASSERT(x,...) {if(!(x)){YT_CLIENT_ERROR("断言错误:{0}",__VA_ARGS__);__debugbreak();}}
    22. #define YT_CORE_ASSERT(x,...) {if(!(x)){YT_CORE_ERROR("断言错误:{0}",__VA_ARGS__);__debugbreak();}}
    23. #else
    24. #define YT_CLIENT_ASSERT(x,...)
    25. #define YT_CORE_ASSERT(x,...)
    26. #endif // YT_ENABLE_ASSERTS
    27. #define BIT(x)(1<
    28. //绑定事件定义
    29. #define YT_BIND_EVENT_FN(fn) std::bind(&fn, this, std::placeholders::_1)
    30. namespace YOTO {
    31. template<typename T>
    32. using Scope = std::unique_ptr;
    33. template<typename T>
    34. using Ref = std::shared_ptr;
    35. template<typename T,typename ...Args>
    36. constexpr Scope CreateScope(Args&&...args) {
    37. return std::make_shared(std::forward(args)...);
    38. }
    39. template<typename T, typename ...Args>
    40. constexpr Ref CreateRef(Args&&...args) {
    41. return std::make_shared(std::forward(args)...);
    42. }
    43. }

    测试:

    cool! 

  • 相关阅读:
    golang八股文整理(持续搬运)
    .netCore .net5,6,7 存日志文件
    MNE绘制自定义通道位置及名字的脑地形图
    【图文并茂】 做开发这么久了,还不会搭建服务器Maven私有仓库?这也太Low了吧
    系统学习Shell之正则表达式
    Scrum敏捷开发:适应变化的核心能力
    EChart常见配置项解析
    1分钟精准预测未来10天天气,谷歌开源GraphCast
    漫画 | 30年后,中国就会有自己的编程语言!
    vue 父组件给子组件传递一个函数,子组件调用父组件中的方法
  • 原文地址:https://blog.csdn.net/weixin_61943345/article/details/136233386