跟着cherno手搓游戏引擎【12】渲染context和首个三角形

2024-01-28 07:44

本文主要是介绍跟着cherno手搓游戏引擎【12】渲染context和首个三角形,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

渲染上下文:

目的:修改WindowsWindow的结构,把glad抽离出来

WindowsWindow.h:新建m_Context

#pragma once
#include "YOTO/Window.h"
#include <YOTO/Renderer/GraphicsContext.h>
#include<GLFW/glfw3.h>
#include"YOTO/Log.h"struct GLFWwindow;
namespace YOTO {class WindowsWindow :public Window{public :WindowsWindow(const WindowProps& props);virtual ~WindowsWindow();void OnUpdate() override;inline unsigned int GetWidth() const override { return m_Data.Width; };inline unsigned int GetHeight() const override { return m_Data.Height; };inline void SetEventCallback(const EventCallbackFn& callback)override{ m_Data.EventCallback = callback; };void SetVSync(bool enable) ;bool IsVSync()const;//返回windowinline virtual void* GetNativeWindow() const { return m_Window; }private: virtual void Init(const WindowProps& props);virtual void ShutDown();private:GLFWwindow* m_Window;GraphicsContext* m_Context;struct WindowData {std::string Title;unsigned int Width, Height;bool VSync;EventCallbackFn EventCallback;};WindowData m_Data;};
}

WindowsWindow.cpp:把glad的API全部替换成m_Context的方法:

#include "ytpch.h"
#include "WindowsWindow.h"#include"YOTO/Event/ApplicationEvent.h"
#include"YOTO/Event/MouseEvent.h"
#include"YOTO/Event/KeyEvent.h"#include"Platform/OpenGL/OpenGLContext.h"
namespace YOTO {static bool s_GLFWInitialized = false;Window* Window::Creat(const WindowProps& props) {return new WindowsWindow(props);}WindowsWindow::WindowsWindow(const WindowProps& props) {Init(props);}WindowsWindow::~WindowsWindow() {ShutDown();}void WindowsWindow::Init(const WindowProps& props) {m_Data.Title = props.Title;m_Data.Width = props.Width;m_Data.Height = props.Height;YT_CORE_INFO("WindowsWindow:创建了{0},{1},{2}", props.Title, props.Width, props.Height);if (!s_GLFWInitialized) {int success = glfwInit();YT_CLIENT_ASSERT("WindowsWindow:不能创建新的glfw,{0}",success );glfwSetErrorCallback([](int error_code, const char* description) {YT_CORE_ERROR("WindowsWindow:GLFW错误:错误码({0}):{1} ", error_code, description);});s_GLFWInitialized = true;}m_Window = glfwCreateWindow((int)props.Width, (int)props.Height, m_Data.Title.c_str(), nullptr, nullptr);m_Context = new OpenGLContext(m_Window);m_Context->Init();glfwSetWindowUserPointer(m_Window, &m_Data);SetVSync(true);//GLFW回调,每次改变调用lambda里的部分//窗口大小回调glfwSetWindowSizeCallback(m_Window, [](GLFWwindow* window, int width, int height) {WindowData& data=*(WindowData*)glfwGetWindowUserPointer(window);data.Width = width;data.Height = height;WindowResizeEvent event(width, height);//调用回调函数data.EventCallback(event);});//窗口关闭回调glfwSetWindowCloseCallback(m_Window, [](GLFWwindow* window) {WindowData& data = *(WindowData*)glfwGetWindowUserPointer(window);WindowCloseEvent event;data.EventCallback(event);});//键盘按键回调glfwSetKeyCallback(m_Window, [](GLFWwindow* window, int key, int scancode, int action, int mods) {WindowData& data = *(WindowData*)glfwGetWindowUserPointer(window);switch (action) {case GLFW_PRESS:{KeyPressedEvent event(key, 0);data.EventCallback(event);break;}case GLFW_RELEASE:{KeyReleasedEvent event(key);data.EventCallback(event);break;}case GLFW_REPEAT:{KeyPressedEvent event(key, 1);data.EventCallback(event);break;}}});//鼠标按键回调glfwSetMouseButtonCallback(m_Window, [](GLFWwindow* window, int button, int action, int mods) {WindowData& data = *(WindowData*)glfwGetWindowUserPointer(window);switch (action){case GLFW_PRESS:{MouseButtonPressedEvent event(button);data.EventCallback(event);break;}case GLFW_RELEASE:{MouseButtonReleasedEvent event(button);data.EventCallback(event);break;}}});//滚轮回调glfwSetScrollCallback(m_Window, [](GLFWwindow* window, double xoffset, double yoffset) {WindowData& data = *(WindowData*)glfwGetWindowUserPointer(window);MouseScrolledEvent event((float)xoffset, (float)yoffset);data.EventCallback(event);});//鼠标位置回调glfwSetCursorPosCallback(m_Window, [](GLFWwindow* window, double xpos, double ypos) {WindowData& data = *(WindowData*)glfwGetWindowUserPointer(window);MouseMovedEvent event((float)xpos, (float)ypos);data.EventCallback(event);});//字符回调glfwSetCharCallback(m_Window, [](GLFWwindow* window, unsigned int codepoint) {WindowData& data = *(WindowData*)glfwGetWindowUserPointer(window);KeyTypedEvent event(codepoint);data.EventCallback(event);});}void WindowsWindow::ShutDown() {glfwDestroyWindow(m_Window);}void WindowsWindow::OnUpdate(){//轮询事件glfwPollEvents();//交换缓冲区m_Context->SwapBuffers();}void WindowsWindow::SetVSync(bool enable) {if (enable)glfwSwapInterval(1);elseglfwSwapInterval(0);m_Data.VSync = enable;}bool WindowsWindow::IsVSync() const {return m_Data.VSync;}
}

新建类:OpenGLContext和GraphicsContext文件如下结构:

 

GraphicsContext.h:作为基类

#pragma oncenamespace YOTO {class GraphicsContext{public:virtual void Init()=0;virtual void SwapBuffers()=0;};
}

 OpenGLContext.h:继承基类

#pragma once
#include"YOTO/Renderer/GraphicsContext.h"
#include"YOTO/Log.h"
struct GLFWwindow;
namespace YOTO {class OpenGLContext:public GraphicsContext{public:OpenGLContext(GLFWwindow * windowHandle);virtual void Init()override;virtual void SwapBuffers()override;private:GLFWwindow* m_WindowHandle;};}

 OpenGLContext.cpp:实现Opengl的上下文:

#include "ytpch.h"
#include "OpenGLContext.h"
#include<GLFW/glfw3.h>
#include<glad/glad.h>
#include<gl/GL.h>
namespace YOTO {OpenGLContext::OpenGLContext(GLFWwindow* windowHandle):m_WindowHandle(windowHandle){YT_CORE_ASSERT(windowHandle, "handle为空");}void OpenGLContext::Init(){glfwMakeContextCurrent(m_WindowHandle);//在运行时获取OpenGL函数地址并将其保存在函数指针中供以后使用int status = gladLoadGLLoader((GLADloadproc)glfwGetProcAddress);YT_CORE_ASSERT(status, "glad初始化错误");}void OpenGLContext::SwapBuffers(){glfwSwapBuffers(m_WindowHandle);}
}

 测试:正常显示

 绘制三角形:

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"
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, m_VertexBuffer, m_IndexBuffer;static Application* s_Instance;};//在客户端定义Application* CreateApplication();
}

 Application.cpp:设置缓冲区然后绘制

#include"ytpch.h"
#include "Application.h"#include"Log.h"
#include<glad/glad.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() {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);//顶点数组:glGenVertexArrays(1, &m_VertexArray);glBindVertexArray(m_VertexArray);//顶点缓冲区glGenBuffers(1, &m_VertexBuffer);glBindBuffer(GL_ARRAY_BUFFER,m_VertexBuffer);float vertices[3 * 3] = {-0.5f,-0.5f,0.0f,0.5f,-0.5f,0.0f,0.0f,0.5f,0.0f,};//把数据传送给gpu,GL_STATIC_DRAW不断的用新数据刷新数组。告诉opengl这个缓冲区的数据布局glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);//启用数据的索引0glEnableVertexAttribArray(0);//设置缓冲区数据格式:缓冲区序号、顶点属性的大小、什么数据类型、会不会被归一化、glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float),nullptr);//创建索引缓冲区glGenBuffers(1, &m_IndexBuffer);glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_IndexBuffer);unsigned int indices[3] = { 0,1,2 };//设置缓冲区格式glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);//着色器//shader}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){glClearColor(0.2f, 0.2f, 0.2f,1);glClear(GL_COLOR_BUFFER_BIT);glBindVertexArray(m_VertexArray);glDrawElements(GL_TRIANGLES,3,GL_UNSIGNED_INT,nullptr); 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();}
}

 OpenGLContext.cpp:显示显卡的基本信息:

#include "ytpch.h"
#include "OpenGLContext.h"
#include<GLFW/glfw3.h>
#include<glad/glad.h>
#include<gl/GL.h>
namespace YOTO {OpenGLContext::OpenGLContext(GLFWwindow* windowHandle):m_WindowHandle(windowHandle){YT_CORE_ASSERT(windowHandle, "handle为空");}void OpenGLContext::Init(){glfwMakeContextCurrent(m_WindowHandle);//在运行时获取OpenGL函数地址并将其保存在函数指针中供以后使用int status = gladLoadGLLoader((GLADloadproc)glfwGetProcAddress);YT_CORE_ASSERT(status, "glad初始化错误");// 将我们窗口的上下文设置为当前线程的主上下文glfwMakeContextCurrent(m_WindowHandle);// 获取显卡OpenGL函数定义的地址int statu = gladLoadGLLoader((GLADloadproc)glfwGetProcAddress);YT_CORE_ASSERT(status, "Failed to initialize Glad!");YT_CORE_INFO("OpenGL 信息:");YT_CORE_INFO("	Vendor:{0}", (const char*)glGetString(GL_VENDOR));YT_CORE_INFO("	显卡名:{0}", (const char*)glGetString(GL_RENDERER));YT_CORE_INFO("	版本:{0}", (const char*)glGetString(GL_VERSION));}void OpenGLContext::SwapBuffers(){glfwSwapBuffers(m_WindowHandle);}
}

 测试:

cool !

这篇关于跟着cherno手搓游戏引擎【12】渲染context和首个三角形的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/652954

相关文章

MySQL常见的存储引擎和区别说明

《MySQL常见的存储引擎和区别说明》MySQL支持多种存储引擎,如InnoDB、MyISAM、MEMORY、Archive、CSV和Blackhole,每种引擎有其特点和适用场景,选择存储引擎时需根... 目录mysql常见的存储引擎和区别说明1. InnoDB2. MyISAM3. MEMORY4. A

MySQL InnoDB引擎ibdata文件损坏/删除后使用frm和ibd文件恢复数据

《MySQLInnoDB引擎ibdata文件损坏/删除后使用frm和ibd文件恢复数据》mysql的ibdata文件被误删、被恶意修改,没有从库和备份数据的情况下的数据恢复,不能保证数据库所有表数据... 参考:mysql Innodb表空间卸载、迁移、装载的使用方法注意!此方法只适用于innodb_fi

详解如何在React中执行条件渲染

《详解如何在React中执行条件渲染》在现代Web开发中,React作为一种流行的JavaScript库,为开发者提供了一种高效构建用户界面的方式,条件渲染是React中的一个关键概念,本文将深入探讨... 目录引言什么是条件渲染?基础示例使用逻辑与运算符(&&)使用条件语句列表中的条件渲染总结引言在现代

Python基于火山引擎豆包大模型搭建QQ机器人详细教程(2024年最新)

《Python基于火山引擎豆包大模型搭建QQ机器人详细教程(2024年最新)》:本文主要介绍Python基于火山引擎豆包大模型搭建QQ机器人详细的相关资料,包括开通模型、配置APIKEY鉴权和SD... 目录豆包大模型概述开通模型付费安装 SDK 环境配置 API KEY 鉴权Ark 模型接口Prompt

Python开发围棋游戏的实例代码(实现全部功能)

《Python开发围棋游戏的实例代码(实现全部功能)》围棋是一种古老而复杂的策略棋类游戏,起源于中国,已有超过2500年的历史,本文介绍了如何用Python开发一个简单的围棋游戏,实例代码涵盖了游戏的... 目录1. 围棋游戏概述1.1 游戏规则1.2 游戏设计思路2. 环境准备3. 创建棋盘3.1 棋盘类

【WebGPU Unleashed】1.1 绘制三角形

一部2024新的WebGPU教程,作者Shi Yan。内容很好,翻译过来与大家共享,内容上会有改动,加上自己的理解。更多精彩内容尽在 dt.sim3d.cn ,关注公众号【sky的数孪技术】,技术交流、源码下载请添加微信号:digital_twin123 在 3D 渲染领域,三角形是最基本的绘制元素。在这里,我们将学习如何绘制单个三角形。接下来我们将制作一个简单的着色器来定义三角形内的像素

国产游戏崛起:技术革新与文化自信的双重推动

近年来,国产游戏行业发展迅猛,技术水平和作品质量均得到了显著提升。特别是以《黑神话:悟空》为代表的一系列优秀作品,成功打破了过去中国游戏市场以手游和网游为主的局限,向全球玩家展示了中国在单机游戏领域的实力与潜力。随着中国开发者在画面渲染、物理引擎、AI 技术和服务器架构等方面取得了显著进展,国产游戏正逐步赢得国际市场的认可。然而,面对全球游戏行业的激烈竞争,国产游戏技术依然面临诸多挑战,未来的

MiniGPT-3D, 首个高效的3D点云大语言模型,仅需一张RTX3090显卡,训练一天时间,已开源

项目主页:https://tangyuan96.github.io/minigpt_3d_project_page/ 代码:https://github.com/TangYuan96/MiniGPT-3D 论文:https://arxiv.org/pdf/2405.01413 MiniGPT-3D在多个任务上取得了SoTA,被ACM MM2024接收,只拥有47.8M的可训练参数,在一张RTX

速了解MySQL 数据库不同存储引擎

快速了解MySQL 数据库不同存储引擎 MySQL 提供了多种存储引擎,每种存储引擎都有其特定的特性和适用场景。了解这些存储引擎的特性,有助于在设计数据库时做出合理的选择。以下是 MySQL 中几种常用存储引擎的详细介绍。 1. InnoDB 特点: 事务支持:InnoDB 是一个支持 ACID(原子性、一致性、隔离性、持久性)事务的存储引擎。行级锁:使用行级锁来提高并发性,减少锁竞争

火柴游戏java版

代码 /*** 火柴游戏* <p>* <li>有24根火柴</li>* <li>组成 A + B = C 等式</li>* <li>总共有多少种适合方式?</li>* <br>* <h>分析:</h>* <li>除去"+"、"="四根,最多可用火柴根数20根。</li>* <li>全部用两根组合成"1",最大数值为1111。使用枚举法,A和B范围在0~1111,C为A+B。判断</li>** @