相机封装:
OrthographicCamera.h:
#pragma once
#include <glm/glm.hpp>
namespace YOTO {class OrthographicCamera{public:OrthographicCamera(float left,float right , float bottom,float top);const glm::vec3& GetPosition()const { return m_Position; }void SetPosition(const glm::vec3& position) { m_Position = position; RecalculateViewMatrix();}float GetRotation()const { return m_Rotation; }void SetRotation(float rotation) {m_Rotation = rotation; RecalculateViewMatrix();}const glm::mat4& GetProjectionMatrix()const { return m_ProjectionMatrix; }const glm::mat4& GetViewMatrix()const { return m_ViewMatrix; }const glm::mat4& GetViewProjectionMatrix()const { return m_ViewProjectionMatrix; }private:void RecalculateViewMatrix();private:glm::mat4 m_ProjectionMatrix;glm::mat4 m_ViewMatrix;glm::mat4 m_ViewProjectionMatrix;glm::vec3 m_Position = { 0.0f ,0.0f ,0.0f };float m_Rotation = 0.0f;};
}
OrthographicCamera.cpp:
#include "ytpch.h"
#include "OrthographicCamera.h"
#include <glm/gtc/matrix_transform.hpp>
namespace YOTO {OrthographicCamera::OrthographicCamera(float left, float right, float bottom, float top):m_ProjectionMatrix(glm::ortho(left,right,bottom,top)),m_ViewMatrix(1.0f) {m_ViewProjectionMatrix = m_ProjectionMatrix * m_ViewMatrix;}void OrthographicCamera::RecalculateViewMatrix(){glm::mat4 transform = glm::translate(glm::mat4(1.0f), m_Position)*glm::rotate(glm::mat4(1.0f),glm::radians(m_Rotation),glm::vec3(0,0,1));m_ViewMatrix = glm::inverse(transform);m_ViewProjectionMatrix = m_ProjectionMatrix * m_ViewMatrix;}
}
Uniform的封装:
Shader.h:
#pragma once
#include <string>
#include <glm/glm.hpp>
namespace YOTO {class Shader {public:Shader(const std::string& vertexSrc, const std::string& fragmentSrc);~Shader();void Bind()const;void UnBind()const;void UploadUniformMat4(const std::string&name, const glm::mat4 & matrix);private:uint32_t m_RendererID;}
;
}
Shader.cpp:
#include"ytpch.h"
#include "Shader.h"
#include <glad/glad.h>
#include <YOTO/Log.h>
#include<glm/gtc/type_ptr.hpp>
namespace YOTO {Shader::Shader(const std::string& vertexSrc, const std::string& fragmentSrc){// 1.1.创建顶点着色器对象GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);// Send the vertex shader source code to GL// Note that std::string's .c_str is NULL character terminated.// 1.2.附加顶点着色器源码到顶点着色器对象中const GLchar* source = vertexSrc.c_str();glShaderSource(vertexShader, 1, &source, 0);// 1.3.编译顶点着色器对象glCompileShader(vertexShader);// 1.4.检查是否编译成功GLint isCompiled = 0;glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &isCompiled);if (isCompiled == GL_FALSE) {// 1.4.2编译失败可以打印报错信息GLint maxLength = 0;glGetShaderiv(vertexShader, GL_INFO_LOG_LENGTH, &maxLength);// The maxLength includes the NULL characterstd::vector<GLchar> infoLog(maxLength);glGetShaderInfoLog(vertexShader, maxLength, &maxLength, &infoLog[0]);// We don't need the shader anymore.glDeleteShader(vertexShader);YT_CORE_ERROR("{0}", infoLog.data());YT_CORE_ASSERT(false, "Vertex shader compilation failure!");return;}// 片段着色器一样// 2.1.创建片段着色器对象GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);// Send the fragment shader source code to GL// Note that std::string's .c_str is NULL character terminated.// 2.2.附加片段着色器源码到片段着色器对象中source = fragmentSrc.c_str();glShaderSource(fragmentShader, 1, &source, 0);// 2.3.编译片段着色器对象glCompileShader(fragmentShader);// 2.4.检查是否编译成功glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &isCompiled);if (isCompiled == GL_FALSE) {// 2.4.2编译失败可以打印报错信息GLint maxLength = 0;glGetShaderiv(fragmentShader, GL_INFO_LOG_LENGTH, &maxLength);// The maxLength includes the NULL characterstd::vector<GLchar> infoLog(maxLength);glGetShaderInfoLog(fragmentShader, maxLength, &maxLength, &infoLog[0]);// We don't need the shader anymore.glDeleteShader(fragmentShader);// Either of them. Don't leak shaders.glDeleteShader(vertexShader);YT_CORE_ERROR("{0}", infoLog.data());YT_CORE_ASSERT(false, "Fragment shader compilation failure!");return;}// Vertex and fragment shaders are successfully compiled.// Now time to link them together into a program.// Get a program object.// 3.1创建着色器程序对象m_RendererID = glCreateProgram();GLuint program = m_RendererID;// 3.2附加着色器对象给着色器程序对象glAttachShader(program, vertexShader);glAttachShader(program, fragmentShader);// 3.3链接着色器程序对象glLinkProgram(program);// 3.4可以检查链接是否成功// Note the different functions here: glGetProgram* instead of glGetShader*.GLint isLinked = 0;glGetProgramiv(program, GL_LINK_STATUS, (int*)&isLinked);if (isLinked == GL_FALSE) {GLint maxLength = 0;glGetProgramiv(program, GL_INFO_LOG_LENGTH, &maxLength);// The maxLength includes the NULL characterstd::vector<GLchar> infoLog(maxLength);glGetProgramInfoLog(program, maxLength, &maxLength, &infoLog[0]);// We don't need the program anymore.glDeleteProgram(program);// Don't leak shaders either.glDeleteShader(vertexShader);glDeleteShader(fragmentShader);YT_CORE_ERROR("{0}", infoLog.data());YT_CORE_ASSERT(false, "Shader link failure!");return;}// 4.删除着色器对象// Always detach shaders after a successful link.glDetachShader(program, vertexShader);glDetachShader(program, fragmentShader);}Shader::~Shader(){glDeleteProgram(m_RendererID);}void Shader::Bind() const{glUseProgram(m_RendererID);}void Shader::UnBind() const{glUseProgram(0);}void Shader::UploadUniformMat4(const std::string& name, const glm::mat4& matrix){GLint loacation= glGetUniformLocation(m_RendererID, name.c_str());glUniformMatrix4fv(loacation, 1, GL_FALSE,glm::value_ptr(matrix));}
}
进一步封装ShaderUniform:
Renderer.h:
#pragma once
#include"RenderCommand.h"
#include "OrthographicCamera.h"
#include"Shader.h"
namespace YOTO {class Renderer {public:static void BeginScene(OrthographicCamera &camera);static void EndScene();static void Submit(const std::shared_ptr<Shader>& shader, const std::shared_ptr<VertexArray>& vertexArray);inline static RendererAPI::API GetAPI() {return RendererAPI::GetAPI();}private:struct SceneData {glm::mat4 ViewProjectionMatrix;};static SceneData* m_SceneData;};}
Renderer.cpp:
#include"ytpch.h"
#include"Renderer.h"
namespace YOTO {Renderer::SceneData* Renderer::m_SceneData = new Renderer::SceneData;void Renderer::BeginScene(OrthographicCamera& camera){m_SceneData->ViewProjectionMatrix = camera.GetViewProjectionMatrix();}void Renderer::EndScene(){}void Renderer::Submit( const std::shared_ptr<Shader>& shader,const std::shared_ptr<VertexArray>& vertexArray){shader->Bind();shader->UploadUniformMat4("u_ViewProjection", m_SceneData->ViewProjectionMatrix);vertexArray->Bind();RenderCommand::DrawIndexed(vertexArray);}
}
调用:
Application.h:
#pragma once
#include"Core.h"
#include"Event/Event.h"
#include"Event/ApplicationEvent.h"
#include "YOTO/Window.h"
#include"YOTO/LayerStack.h"
#include"YOTO/ImGui/ImGuiLayer.h"#include <YOTO/Renderer/Shader.h>
#include <YOTO/Renderer/Buffer.h>
#include <YOTO/Renderer/VertexArray.h>#include "YOTO/Renderer/OrthographicCamera.h"
namespace YOTO {class YOTO_API Application{public:Application();virtual ~Application();void Run();void OnEvent(Event &e);void PushLayer(Layer* layer);void PushOverlay(Layer* layer);inline static Application& Get() {return * s_Instance;}inline Window& GetWindow() { return *m_Window; }private:bool OnWindowClosed(WindowCloseEvent& e);std::unique_ptr<Window> m_Window;ImGuiLayer * m_ImGuiLayer;bool m_Running = true;LayerStack m_LayerStack;//unsigned int m_VertexArray;std::shared_ptr<Shader> m_Shader;std::shared_ptr<VertexArray> m_VertexArray;std::shared_ptr<Shader> m_BlueShader;std::shared_ptr<VertexArray> m_SquareVA;OrthographicCamera m_Camera;private:static Application* s_Instance;};//在客户端定义Application* CreateApplication();
}
Application.cpp:
#include"ytpch.h"
#include "Application.h"#include"Log.h"
#include "YOTO/Renderer/Renderer.h"
#include"Input.h"namespace YOTO {
#define BIND_EVENT_FN(x) std::bind(&x, this, std::placeholders::_1)Application* Application::s_Instance = nullptr;Application::Application():m_Camera(-2.0f,2.0f,-2.0f,2.0f){YT_CORE_ASSERT(!s_Instance, "Application需要为空!")s_Instance = this;//智能指针m_Window = std::unique_ptr<Window>(Window::Creat());//设置回调函数m_Window->SetEventCallback(BIND_EVENT_FN(Application::OnEvent));//new一个Layer,放在最后层进行渲染m_ImGuiLayer = new ImGuiLayer();PushOverlay(m_ImGuiLayer); //unsigned int id;//glGenBuffers(1, &id);uint32_t indices[3] = { 0,1,2 };float vertices[3 * 7] = {-0.5f,-0.5f,0.0f, 0.8f,0.2f,0.8f,1.0f,0.5f,-0.5f,0.0f, 0.2f,0.3f,0.8f,1.0f,0.0f,0.5f,0.0f, 0.8f,0.8f,0.2f,1.0f,};m_VertexArray.reset(VertexArray::Create());std::shared_ptr<VertexBuffer> m_VertexBuffer;m_VertexBuffer.reset(VertexBuffer::Create(vertices, sizeof(vertices)));{BufferLayout setlayout = {{ShaderDataType::Float3,"a_Position"},{ShaderDataType::Float4,"a_Color"}};m_VertexBuffer->SetLayout(setlayout);}m_VertexArray->AddVertexBuffer(m_VertexBuffer);std::shared_ptr<IndexBuffer>m_IndexBuffer;m_IndexBuffer.reset(IndexBuffer::Create(indices, sizeof(indices)/sizeof(uint32_t)));m_VertexArray->AddIndexBuffer(m_IndexBuffer);std::string vertexSource = R"(#version 330 corelayout(location = 0) in vec3 a_Position;layout(location = 1) in vec4 a_Color;uniform mat4 u_ViewProjection;out vec3 v_Position;out vec4 v_Color;void main(){v_Position=a_Position;v_Color=a_Color;gl_Position =u_ViewProjection*vec4( a_Position,1.0);})";//绘制颜色std::string fragmentSource = R"(#version 330 corelayout(location = 0) out vec4 color;in vec3 v_Position;in vec4 v_Color;void main(){color=vec4(v_Color);})";m_Shader.reset(new Shader(vertexSource, fragmentSource));///测试/m_SquareVA.reset(VertexArray::Create());float squareVertices[3 * 4] = {-0.5f,-0.5f,0.0f,0.5f,-0.5f,0.0f, 0.5f,0.5f,0.0f,-0.5f,0.5f,0.0f};std::shared_ptr<VertexBuffer> squareVB;squareVB.reset(VertexBuffer::Create(squareVertices, sizeof(squareVertices)));squareVB->SetLayout({{ShaderDataType::Float3,"a_Position"}});m_SquareVA->AddVertexBuffer(squareVB);uint32_t squareIndices[6] = { 0,1,2,2,3,0 };std::shared_ptr<IndexBuffer> squareIB; squareIB.reset((IndexBuffer::Create(squareIndices, sizeof(squareIndices) / sizeof(uint32_t))));m_SquareVA->AddIndexBuffer(squareIB);//测试:std::string BlueShaderVertexSource = R"(#version 330 corelayout(location = 0) in vec3 a_Position;uniform mat4 u_ViewProjection;out vec3 v_Position;void main(){v_Position=a_Position;gl_Position =u_ViewProjection*vec4( a_Position,1.0);})";//绘制颜色std::string BlueShaderFragmentSource = R"(#version 330 corelayout(location = 0) out vec4 color;in vec3 v_Position;void main(){color=vec4(0.2,0.3,0.8,1.0);})";m_BlueShader.reset(new Shader(BlueShaderVertexSource, BlueShaderFragmentSource));}Application::~Application() {}/// <summary>/// 所有的Window事件都会在这触发,作为参数e/// </summary>/// <param name="e"></param>void Application::OnEvent(Event& e) {//根据事件类型绑定对应事件EventDispatcher dispatcher(e);dispatcher.Dispatch<WindowCloseEvent>(BIND_EVENT_FN(Application::OnWindowClosed));//输出事件信息YT_CORE_INFO("Application:{0}",e);for (auto it = m_LayerStack.end(); it != m_LayerStack.begin();) {(*--it)->OnEvent(e);if (e.m_Handled)break;}}bool Application::OnWindowClosed(WindowCloseEvent& e) {m_Running = false;return true;}void Application::Run() {WindowResizeEvent e(1280, 720);if (e.IsInCategory(EventCategoryApplication)) {YT_CORE_TRACE(e);}if (e.IsInCategory(EventCategoryInput)) {YT_CORE_ERROR(e);}while (m_Running){RenderCommand::SetClearColor({0.2f, 0.2f, 0.2f, 1.0f});RenderCommand::Clear();m_Camera.SetPosition({0.5f,0.5f, 0.0f });m_Camera.SetRotation(45);Renderer::BeginScene(m_Camera);{/* m_BlueShader->Bind();m_BlueShader->UploadUniformMat4("u_ViewProjection",m_Camera.GetViewProjectionMatrix());*/Renderer::Submit(m_BlueShader,m_SquareVA);/* m_Shader->Bind();m_Shader->UploadUniformMat4("u_ViewProjection", m_Camera.GetViewProjectionMatrix());*/Renderer::Submit(m_Shader,m_VertexArray);Renderer::EndScene();}for (Layer* layer : m_LayerStack) {layer->OnUpdate();}//将ImGui的刷新放到APP中,与Update分开m_ImGuiLayer->Begin();for (Layer* layer : m_LayerStack) {layer->OnImGuiRender();}m_ImGuiLayer->End();m_Window->OnUpdate();}}void Application::PushLayer(Layer* layer) {m_LayerStack.PushLayer(layer);layer->OnAttach();}void Application::PushOverlay(Layer* layer) {m_LayerStack.PushOverlay(layer);layer->OnAttach();}
}
测试:
cool!
目前代码比较潦草,甚至有些地方没有注释。计划在渲染出第一个兰伯特模型时对代码架构进行总结。