Added a few thing , and started simplifying renderer
- Added context menu to Inspector - Added check to see if project path exists. - Simplifying the renderer design
This commit is contained in:
parent
550c1b6e5b
commit
daf26c304b
@ -16,6 +16,10 @@ public:
|
||||
AssetFinder () : EditorWindow("Assets") {}
|
||||
AssetFinder(const std::filesystem::path& projectdirectory) : EditorWindow("Assets")
|
||||
{
|
||||
assetIcon = YoggieEngine::Texture("rsc/AssetIcon.png");
|
||||
|
||||
spdlog::info("asset iconID: {0}", assetIcon.GetID());
|
||||
|
||||
for (auto& dir_entry : std::filesystem::directory_iterator(projectdirectory)) {
|
||||
auto filepath = dir_entry.path();
|
||||
|
||||
@ -39,7 +43,6 @@ public:
|
||||
spdlog::info("Created asset: {0}", asset.GetName());
|
||||
files.push_back(asset);
|
||||
|
||||
assetIcon = YoggieEngine::Texture("rsc/AssetIcon.png");
|
||||
|
||||
}
|
||||
|
||||
|
@ -8,9 +8,7 @@ public:
|
||||
Right = glm::vec3(-1.0f, 0.0f, 0.0f);
|
||||
Up = glm::vec3(0.0f, 1.0f, 0.0f);
|
||||
|
||||
projection = glm::perspective(glm::radians(65.0f), (800.0f / 600.0f), 0.001f, 100.0f);
|
||||
|
||||
|
||||
|
||||
view = glm::translate(glm::mat4(1.0f), Position) * glm::toMat4(glm::quat(Rotation));
|
||||
}
|
||||
|
||||
@ -19,8 +17,8 @@ public:
|
||||
view = glm::translate(glm::mat4(1.0f), Position) * glm::toMat4(glm::quat(Rotation));
|
||||
}
|
||||
|
||||
glm::vec3 Position;
|
||||
glm::vec3 Rotation;
|
||||
glm::vec3 Position = glm::vec3(0.0f);
|
||||
glm::vec3 Rotation = glm::vec3(0.0f);
|
||||
|
||||
private:
|
||||
|
||||
|
@ -17,15 +17,34 @@
|
||||
#include "IconsMaterialDesign.h"
|
||||
#include "Project/Project.h"
|
||||
#include <ImGuizmo.h>
|
||||
#include "EditorCamera.h"
|
||||
#include "../../YoggieEngine/src/Graphics/Memory/VertexArray.h"
|
||||
#include "../../YoggieEngine/src/Graphics/Memory/Buffer.h"
|
||||
|
||||
using namespace YoggieEngine;
|
||||
class EditorLayer : public Layer {
|
||||
|
||||
public:
|
||||
EditorLayer():
|
||||
EditorLayer() :
|
||||
Layer(),
|
||||
inspector (Selected)
|
||||
Logo("rsc/Yoggie.png"),
|
||||
inspector(Selected),
|
||||
scene(),
|
||||
renderer()
|
||||
{
|
||||
|
||||
spdlog::info("Colour attachment id: {0}", renderer.getCurrentFrameBuffer().GetColourAttachment());
|
||||
|
||||
Selected = YoggieEngine::Entity((entt::entity)-1, &scene);
|
||||
|
||||
AssetRegistry assetManager = AssetRegistry();
|
||||
// ModelLoader modelLoader = ModelLoader();
|
||||
|
||||
spdlog::info("{0}", project.GetProjectDirectory().string());
|
||||
|
||||
//auto latern = modelLoader.LoadAsset(std::filesystem::path("build/debug/Models/Latern.gltf"));
|
||||
//spdlog::info("Loaded mesh: {0}", latern.GetName());
|
||||
|
||||
}
|
||||
|
||||
void OnStartup() override {
|
||||
@ -33,27 +52,13 @@ public:
|
||||
project.setProjectDirectory(path);
|
||||
assetsView = AssetFinder(project.GetProjectDirectory());
|
||||
LoadLastOrEmptyProject();
|
||||
|
||||
AssetRegistry assetManager = AssetRegistry();
|
||||
ModelLoader modelLoader = ModelLoader();
|
||||
|
||||
spdlog::info( "{0}", project.GetProjectDirectory().string());
|
||||
|
||||
auto latern = modelLoader.LoadAsset(std::filesystem::path("build/debug/Models/Latern.gltf"));
|
||||
spdlog::info( "Loaded mesh: {0}" , latern.GetName() );
|
||||
|
||||
|
||||
cube = (ModelLoader()).LoadAsset(std::filesystem::path("build/debug/Models/cube.obj"));
|
||||
//Settings settings = Settings();
|
||||
//Console console = Console();
|
||||
|
||||
Logo = Texture("rsc/Yoggie.png", true);
|
||||
|
||||
|
||||
|
||||
Selected = YoggieEngine::Entity((entt::entity)-1, &scene);
|
||||
|
||||
}
|
||||
|
||||
glm::vec3 cameraPosition = glm::vec3(0.0f, 0.0f, -5.0f);
|
||||
glm::vec3 cameraRotation = glm::vec3(0.0f);
|
||||
void OnUpdate() override {
|
||||
scene.Update();
|
||||
/*
|
||||
@ -61,13 +66,59 @@ public:
|
||||
UpdateSceneCamera(sceneview);
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
auto components = scene.getReg().view<Render3DComponent>();
|
||||
for(auto component : components){
|
||||
auto& renderComponent = YoggieEngine::Entity(component, &scene).GetComponent<Render3DComponent>();
|
||||
|
||||
renderComponent.mesh = cube;
|
||||
|
||||
if (renderComponent.VAO == 0 || renderComponent.IBO == 0) {
|
||||
VertexArray va = VertexArray();
|
||||
Buffer vertexBuffer = Buffer();
|
||||
Buffer elementBuffer = Buffer();
|
||||
|
||||
va.Create();
|
||||
va.Bind();
|
||||
|
||||
vertexBuffer.createBuffer();
|
||||
vertexBuffer.Bind(false);
|
||||
vertexBuffer.setBufferData((void*)&renderComponent.mesh.vertices[0], renderComponent.mesh.vertices.size() * sizeof(Vertex), false);
|
||||
|
||||
elementBuffer.createBuffer();
|
||||
elementBuffer.Bind(true);
|
||||
elementBuffer.setBufferData((void*)&renderComponent.mesh.elements[0], renderComponent.mesh.elements.size() * sizeof(unsigned int), true);
|
||||
|
||||
va.AttachAttribute(0, 3, sizeof(Vertex));
|
||||
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)0);
|
||||
glEnableVertexAttribArray(0);
|
||||
glEnableVertexAttribArray(1);
|
||||
|
||||
va.Unbind();
|
||||
vertexBuffer.Unbind(false);
|
||||
elementBuffer.Unbind(true);
|
||||
|
||||
renderComponent.VAO = va.getID();
|
||||
renderComponent.IBO = elementBuffer.getBufferID();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
camera->view = glm::translate(glm::mat4(1.0f), cameraPosition) * glm::toMat4(glm::quat(cameraRotation));
|
||||
|
||||
renderer.Render(scene, *camera);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
void OnUI() override {
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, { ImGui::GetWindowWidth(), 7 });
|
||||
ImGui::BeginMainMenuBar();
|
||||
int scaleFactor = 30;
|
||||
@ -216,7 +267,6 @@ public:
|
||||
ImGui::SameLine(ImGui::GetWindowWidth() - 120);
|
||||
|
||||
/*
|
||||
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.1f, 0.1f, 0.1f, 0.01f));
|
||||
if (ImGui::Button(ICON_MD_MINIMIZE)) { spdlog::info("Minimize"); }
|
||||
@ -268,9 +318,17 @@ public:
|
||||
ImGui::End();
|
||||
|
||||
|
||||
ImGui::Begin("SceneView");
|
||||
unsigned int viewportWindowFlags = ImGuiWindowFlags_NoTitleBar
|
||||
| ImGuiWindowFlags_NoDecoration
|
||||
| ImGuiWindowFlags_NoScrollbar
|
||||
| ImGuiWindowFlags_NoMove
|
||||
| ImGuiWindowFlags_NoCollapse;
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2{ 0,0 });
|
||||
ImGui::Begin("SceneView",nullptr,viewportWindowFlags);
|
||||
spdlog::info( "Editor Resolution {0}x{1}", (float)ImGui::GetWindowWidth(),(float)ImGui::GetWindowHeight());
|
||||
|
||||
//ImGui::Image((ImTextureID)gameScreen.GetID(), gameScreen.getSize());
|
||||
ImGui::Image((ImTextureID)(intptr_t)renderer.getCurrentFrameBuffer().GetColourAttachment(),
|
||||
ImVec2{(float)ImGui::GetWindowWidth(),(float)ImGui::GetWindowHeight()});
|
||||
|
||||
ImGuizmo::Enable(true);
|
||||
ImGuizmo::SetOrthographic(false);
|
||||
@ -295,6 +353,15 @@ public:
|
||||
*/
|
||||
|
||||
ImGui::End();
|
||||
ImGui::PopStyleVar();
|
||||
|
||||
ImGui::Begin("EditorCamera");
|
||||
|
||||
ImGui::SliderFloat3("position", glm::value_ptr(cameraPosition), -50, 50);
|
||||
ImGui::End();
|
||||
|
||||
|
||||
|
||||
|
||||
ImGui::Begin(ICON_MD_MENU "SceneExplorer",nullptr);
|
||||
scene.getReg().each([&](entt::entity enttNumber) {
|
||||
@ -302,8 +369,11 @@ public:
|
||||
auto id = entity.GetComponent<YoggieEngine::IdentifierComponent>();
|
||||
if (ImGui::Selectable(id.name.c_str(), entity == Selected)) {
|
||||
Selected = YoggieEngine::Entity(enttNumber, &scene);
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
ImGui::End();
|
||||
|
||||
inspector.Update();
|
||||
@ -340,7 +410,9 @@ private:
|
||||
Scene scene;
|
||||
char* path = nullptr;
|
||||
Texture Logo;
|
||||
|
||||
Renderer renderer;
|
||||
Camera* camera = new EditorCamera();
|
||||
Mesh cube ;
|
||||
|
||||
void LoadLastOrEmptyProject() {
|
||||
// Check if there is a last known loaded project and
|
||||
|
@ -31,6 +31,11 @@ void Project::SaveProject(std::filesystem::path path, Project& project)
|
||||
|
||||
void Project::LoadProject(std::filesystem::path path, Project& project)
|
||||
{
|
||||
|
||||
if (!std::filesystem::exists(path)) {
|
||||
throw std::runtime_error("Couldn't find project file!");
|
||||
}
|
||||
|
||||
std::string YAMLProject;
|
||||
std::stringstream sstream;
|
||||
std::ifstream projectFile;
|
||||
@ -47,7 +52,7 @@ void Project::LoadProject(std::filesystem::path path, Project& project)
|
||||
// this is probably not perfect but it seems to work for now
|
||||
project = node.as<Project>();
|
||||
|
||||
std::cout << "loading..." << project.Name << std::endl;
|
||||
spdlog::info("loaded project {0}", project.Name);
|
||||
|
||||
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "Inspector.h"
|
||||
#include "../TransformVec3.h"
|
||||
#include "../IconsMaterialDesign.h"
|
||||
|
||||
void Inspector::Draw()
|
||||
{
|
||||
@ -56,6 +57,28 @@ void Inspector::ShowComponents()
|
||||
if (selected.HasComponent<YoggieEngine::TransformComponent>()) {
|
||||
auto& transform = selected.GetComponent<YoggieEngine::TransformComponent>();
|
||||
if (ImGui::CollapsingHeader("Transform", ImGuiTreeNodeFlags_DefaultOpen)) {
|
||||
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4{ 1.0, 1.0f, 1.0f, 0.0f });
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4{ 1.0, 1.0f, 1.0f, 0.0f });
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4{ 1.0, 1.0f, 1.0f, 0.0f });
|
||||
ImGui::SetCursorPosX(ImGui::GetContentRegionMax().x - 20);
|
||||
ImGui::Button(ICON_MD_SETTINGS, { 20,20 });
|
||||
ImGui::OpenPopupOnItemClick("##myContext", ImGuiPopupFlags_MouseButtonRight);
|
||||
if (ImGui::BeginPopupContextWindow("##myContext")) {
|
||||
if (ImGui::MenuItem("Reset")) {
|
||||
spdlog::info("Reset component");
|
||||
}
|
||||
if (ImGui::MenuItem("Copy Component")) {
|
||||
spdlog::info("Copy component");
|
||||
}
|
||||
|
||||
|
||||
ImGui::EndPopup();
|
||||
|
||||
}
|
||||
|
||||
ImGui::PopStyleColor(3);
|
||||
|
||||
/*
|
||||
ImGui::DragFloat3("Position", glm::value_ptr(transform.Position), 0.1f);
|
||||
ImGui::DragFloat3("Rotation", glm::value_ptr(transform.Rotation), 0.1f);
|
||||
|
27
YoggieEngine/src/Graphics/OpenglAPI.cpp
Normal file
27
YoggieEngine/src/Graphics/OpenglAPI.cpp
Normal file
@ -0,0 +1,27 @@
|
||||
#include <YoggieEngine.h>
|
||||
#include "OpenglAPI.h"
|
||||
namespace YoggieEngine {
|
||||
void OpenGLApi::DrawTriangles(Render3DComponent rc) {
|
||||
|
||||
glBindVertexArray(rc.VAO);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, rc.IBO);
|
||||
glDrawElements(GL_TRIANGLES, static_cast<unsigned int> (rc.mesh.elements.size()), GL_UNSIGNED_INT, 0);
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void OpenGLApi::DrawCubeMap(unsigned int VertexAttributeObject, CubeMap CubeTexture) {
|
||||
|
||||
glDepthMask(GL_FALSE);
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, CubeTexture.getID());
|
||||
|
||||
glBindVertexArray(VertexAttributeObject);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||
glBindVertexArray(0);
|
||||
glDepthMask(GL_TRUE);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
9
YoggieEngine/src/Graphics/OpenglAPI.h
Normal file
9
YoggieEngine/src/Graphics/OpenglAPI.h
Normal file
@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
namespace YoggieEngine {
|
||||
class OpenGLApi {
|
||||
public:
|
||||
static void DrawTriangles(Render3DComponent rc);
|
||||
|
||||
static void DrawCubeMap(unsigned int VertexAttributeObject, CubeMap CubeTexture);
|
||||
};
|
||||
};
|
@ -4,7 +4,6 @@
|
||||
#include "../Scene/Components.h"
|
||||
#include "../Graphics/Memory/Buffer.h"
|
||||
#include "../Graphics/Memory/VertexArray.h"
|
||||
#include "../Graphics/Primitives/DrawCommand.h"
|
||||
|
||||
namespace YoggieEngine {
|
||||
unsigned int quadVAO = 0;
|
||||
@ -65,24 +64,40 @@ float skyboxVertices[]{
|
||||
1.0f, -1.0f, 1.0f
|
||||
};
|
||||
|
||||
Renderer::Renderer(RendererConfig& config)
|
||||
: m_framebuffer(Framebuffer(config.ScreenWidth, config.ScreenHeight)),
|
||||
|
||||
Renderer::Renderer() :
|
||||
m_framebuffer(960, 540),
|
||||
gBufferShader("build/Debug/Shaders/deferred/geometry.vert", "build/Debug/Shaders/deferred/geometry.frag"),
|
||||
lightingPassShader("build/Debug/Shaders/deferred/lightPass.vert", "build/Debug/Shaders/deferred/lightPass.frag"),
|
||||
SkyboxShader("build/Debug/Shaders/Cubemaps/Skybox.vert", "build/Debug/Shaders/Cubemaps/Skybox.frag"),
|
||||
BlendingShader("build/Debug/Shaders/forward/Blending.vert", "build/Debug/Shaders/forward/Blending.frag"),
|
||||
forwardShader("build/Debug/Shaders/forward/geometry.vert", "build/Debug/Shaders/forward/geometry.frag"),
|
||||
postProcessingShader("build/Debug/Shaders/forward/postprocessing.vert", "build/Debug/Shaders/forward/postprocessing.frag")
|
||||
{
|
||||
width = config.ScreenWidth;
|
||||
height = config.ScreenHeight;
|
||||
|
||||
|
||||
{
|
||||
width = 960;
|
||||
height = 540;
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
CreateGBuffer();
|
||||
|
||||
std::vector<std::string> faces{
|
||||
"build/Debug/skybox/Open_Water/right.jpg",
|
||||
"build/Debug/skybox/Open_Water/left.jpg",
|
||||
"build/Debug/skybox/Open_Water/top.jpg",
|
||||
"build/Debug/skybox/Open_Water/bottom.jpg",
|
||||
"build/Debug/skybox/Open_Water/front.jpg",
|
||||
"build/Debug/skybox/Open_Water/back.jpg"
|
||||
};
|
||||
|
||||
skybox = CubeMap(faces);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void Renderer::CreateGBuffer() {
|
||||
// Deferred Rendering
|
||||
glGenFramebuffers(1, &gBuffer);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, gBuffer);
|
||||
|
||||
|
||||
// - Position Color Buffer ;
|
||||
glGenTextures(1, &gPosition);
|
||||
glBindTexture(GL_TEXTURE_2D, gPosition);
|
||||
@ -122,326 +137,16 @@ Renderer::Renderer(RendererConfig& config)
|
||||
spdlog::critical("Framebuffer not complete {}{}", __FILE__, __LINE__);
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::vector<std::string> faces{
|
||||
"build/Debug/skybox/Open_Water/right.jpg",
|
||||
"build/Debug/skybox/Open_Water/left.jpg",
|
||||
"build/Debug/skybox/Open_Water/top.jpg",
|
||||
"build/Debug/skybox/Open_Water/bottom.jpg",
|
||||
"build/Debug/skybox/Open_Water/front.jpg",
|
||||
"build/Debug/skybox/Open_Water/back.jpg"
|
||||
};
|
||||
|
||||
sky = CubeMap(faces);
|
||||
|
||||
// Create a skybox vao
|
||||
unsigned int VBO;
|
||||
glGenVertexArrays(1, &skyboxVAO);
|
||||
glGenBuffers(1, &VBO);
|
||||
glBindVertexArray(skyboxVAO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, VBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(skyboxVertices), &skyboxVertices, GL_STATIC_DRAW);
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
|
||||
|
||||
#ifdef WINDOW
|
||||
grassTexture = Texture("build/Debug/Texture/blending_transparent_window.png", true);
|
||||
#else
|
||||
grassTexture = Texture("build/Debug/Texture/grass.png", true);
|
||||
#endif
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
|
||||
}
|
||||
|
||||
|
||||
Renderer::~Renderer(){}
|
||||
|
||||
void SubmitVegetationDemo() {
|
||||
|
||||
|
||||
if (transparentVAO == 0) {
|
||||
float transparentVertices[] = {
|
||||
// positions // texture Coords (swapped y coordinates because texture is flipped upside down)
|
||||
0.0f, 0.5f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, -0.5f, 0.0f, 0.0f, 1.0f,
|
||||
1.0f, -0.5f, 0.0f, 1.0f, 1.0f,
|
||||
|
||||
0.0f, 0.5f, 0.0f, 0.0f, 0.0f,
|
||||
1.0f, -0.5f, 0.0f, 1.0f, 1.0f,
|
||||
1.0f, 0.5f, 0.0f, 1.0f, 0.0f
|
||||
};
|
||||
|
||||
glGenVertexArrays(1, &transparentVAO);
|
||||
glGenBuffers(1, &transparentVBO);
|
||||
glBindVertexArray(transparentVAO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, transparentVBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(transparentVertices), transparentVertices, GL_STATIC_DRAW);
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
|
||||
glBindVertexArray(0);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void Renderer::Submit( Render3DComponent& renderComponent, TransformComponent& transform) {
|
||||
if (renderComponent.mesh.elements.empty())
|
||||
return;
|
||||
|
||||
if (renderComponent.VAO == 0 || renderComponent.IBO == 0)
|
||||
{
|
||||
if (renderComponent.VAO != 0)
|
||||
glDeleteVertexArrays(1, &(renderComponent.VAO));
|
||||
if (renderComponent.IBO != 0)
|
||||
glDeleteBuffers(1, &(renderComponent.IBO));
|
||||
|
||||
VertexArray va = VertexArray();
|
||||
Buffer vertexBuffer = Buffer();
|
||||
Buffer elementBuffer = Buffer();
|
||||
|
||||
va.Create();
|
||||
va.Bind();
|
||||
|
||||
vertexBuffer.createBuffer();
|
||||
vertexBuffer.Bind(false);
|
||||
vertexBuffer.setBufferData((void*)&renderComponent.mesh.vertices[0], renderComponent.mesh.vertices.size() * sizeof(Vertex), false);
|
||||
|
||||
elementBuffer.createBuffer();
|
||||
elementBuffer.Bind(true);
|
||||
elementBuffer.setBufferData((void*)&renderComponent.mesh.elements[0], renderComponent.mesh.elements.size() * sizeof(unsigned int), true);
|
||||
|
||||
va.AttachAttribute(0, 3, sizeof(Vertex));
|
||||
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)0);
|
||||
glEnableVertexAttribArray(0);
|
||||
glEnableVertexAttribArray(1);
|
||||
|
||||
va.Unbind();
|
||||
vertexBuffer.Unbind(false);
|
||||
elementBuffer.Unbind(true);
|
||||
|
||||
renderComponent.VAO = va.getID();
|
||||
renderComponent.IBO = elementBuffer.getBufferID();
|
||||
}
|
||||
|
||||
DrawCommand dc = { renderComponent.isStatic , renderComponent.VAO, renderComponent.mesh.elements.size(), renderComponent.IBO, transform, renderComponent.color };
|
||||
commands.push_back(dc);
|
||||
|
||||
}
|
||||
|
||||
void Renderer::GeometryPass() {
|
||||
// 1.0 Geometry pass
|
||||
gBufferShader.Use();
|
||||
|
||||
for (const DrawCommand& command : commands)
|
||||
{
|
||||
if (command.isDynamic == true)
|
||||
continue;
|
||||
|
||||
glBindVertexArray(command.VAO_identifier);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, command.IBO_identifier);
|
||||
|
||||
gBufferShader.setUniformVec3("Color", command.color);
|
||||
gBufferShader.setUniformMat4("Model", command.transform.LocalTransform);
|
||||
gBufferShader.setUniformMat4("View", MainCamera.view);
|
||||
gBufferShader.setUniformMat4("Projection", MainCamera.projection);
|
||||
|
||||
glDrawElements(GL_TRIANGLES, static_cast<unsigned int>(command.num_elements),
|
||||
GL_UNSIGNED_INT, NULL);
|
||||
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void Renderer::ForwardGeometryPass()
|
||||
{
|
||||
for (const DrawCommand& command : commands)
|
||||
{
|
||||
if (command.isDynamic == false)
|
||||
continue;
|
||||
|
||||
glBindVertexArray(command.VAO_identifier);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, command.IBO_identifier);
|
||||
|
||||
forwardShader.Use();
|
||||
|
||||
forwardShader.setUniformVec3("Color", command.color);
|
||||
forwardShader.setUniformMat4("M", command.transform.LocalTransform);
|
||||
forwardShader.setUniformMat4("V", MainCamera.view);
|
||||
forwardShader.setUniformMat4("P", MainCamera.projection);
|
||||
|
||||
glDrawElements(GL_TRIANGLES, static_cast<unsigned int>(command.num_elements),
|
||||
GL_UNSIGNED_INT, NULL);
|
||||
|
||||
glBindVertexArray(0);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Renderer::SkyboxPass() {
|
||||
// Render skybox
|
||||
glDepthMask(GL_FALSE);
|
||||
SkyboxShader.Use();
|
||||
SkyboxShader.setUniformMat4("projection", MainCamera.projection);
|
||||
SkyboxShader.setUniformMat4("view", glm::mat4(glm::mat3(MainCamera.view))); // remove rotation from the view matrix
|
||||
glBindVertexArray(skyboxVAO);
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, sky.getID());
|
||||
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||
glBindVertexArray(0);
|
||||
glDepthMask(GL_TRUE);
|
||||
|
||||
}
|
||||
|
||||
void Renderer::lightingPass(Scene& scene){
|
||||
|
||||
// 2.0 Lighting Pass
|
||||
|
||||
// configure shader
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer.GetId());
|
||||
|
||||
lightingPassShader.Use();
|
||||
lightingPassShader.setUniformInt("gPosition", 0);
|
||||
lightingPassShader.setUniformInt("gNormal", 1);
|
||||
lightingPassShader.setUniformInt("gColorSpec", 2);
|
||||
|
||||
// Bind all Gbuffer textures
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, gPosition);
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, gNormal);
|
||||
glActiveTexture(GL_TEXTURE2);
|
||||
glBindTexture(GL_TEXTURE_2D, gColorSpec);
|
||||
|
||||
// send relevant Lighting Uniforms
|
||||
auto lights = scene.getReg().view<LightComponent, TransformComponent>();
|
||||
unsigned int lightnr = 0;
|
||||
lights.each([&](auto entity, LightComponent& light, TransformComponent& transform) {
|
||||
lightingPassShader.setUniformVec3("lights[" + std::to_string(lightnr) + "].Position", transform.Position);
|
||||
lightingPassShader.setUniformVec3("lights[" + std::to_string(lightnr) + "].Color", light.Color);
|
||||
|
||||
// Attenuation
|
||||
const float linear = 0.7f;
|
||||
const float quadratic = 1.8f;
|
||||
lightingPassShader.setUniformFloat("lights[" + std::to_string(lightnr) + "].Linear", linear);
|
||||
lightingPassShader.setUniformFloat("lights[" + std::to_string(lightnr) + "].Quadratic", quadratic);
|
||||
|
||||
|
||||
lightnr++;
|
||||
});
|
||||
|
||||
//lightingPassShader.setUniformVec3("viewPos", MainCamera.Position);
|
||||
|
||||
// render to quad
|
||||
if (quadVAO == 0)
|
||||
{
|
||||
float quadVertices[] = {
|
||||
-1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
|
||||
-1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
|
||||
1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
|
||||
1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
|
||||
};
|
||||
// setup plane VAO ;
|
||||
glGenVertexArrays(1, &quadVAO);
|
||||
glGenBuffers(1, &quadVBO);
|
||||
glBindVertexArray(quadVAO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, quadVBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), &quadVertices, GL_STATIC_DRAW);
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
|
||||
}
|
||||
|
||||
|
||||
glBindVertexArray(quadVAO);
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
void Renderer::BlendingPass() {
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
// Vegetation / blending test;
|
||||
BlendingShader.Use();
|
||||
glBindVertexArray(transparentVAO);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, grassTexture.GetID());
|
||||
|
||||
BlendingShader.setUniformMat4("V", MainCamera.view);
|
||||
BlendingShader.setUniformMat4("P", MainCamera.projection);
|
||||
|
||||
|
||||
for (unsigned int i = 0; i < vegetation.size(); i++) {
|
||||
auto rotation = glm::rotate(glm::mat4(1.0f), 45.0f, glm::vec3(0.0f, 1.0f, 0.0f));
|
||||
auto translation = glm::translate(glm::mat4(1.0f), vegetation[i]);
|
||||
auto transform = translation * rotation;
|
||||
BlendingShader.setUniformMat4("M", transform);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
|
||||
}
|
||||
|
||||
glBindVertexArray(0);
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
void Renderer::PostProcessing()
|
||||
{
|
||||
postProcessingShader.Use();
|
||||
postProcessingShader.setUniformInt("screen", 0);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, m_framebuffer.GetColourAttachment());
|
||||
|
||||
|
||||
glBindVertexArray(quadVAO);
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
glBindVertexArray(0);
|
||||
|
||||
|
||||
}
|
||||
|
||||
void Renderer::CopyGBuffer() {
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, gBuffer);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_framebuffer.GetId());
|
||||
glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_DEPTH_BUFFER_BIT, GL_NEAREST);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer.GetId());
|
||||
}
|
||||
|
||||
void Renderer::Render(Scene& scene)
|
||||
{
|
||||
SubmitVegetationDemo();
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, gBuffer);
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
SkyboxPass();
|
||||
|
||||
GeometryPass();
|
||||
|
||||
lightingPass(scene);
|
||||
|
||||
CopyGBuffer();
|
||||
|
||||
ForwardGeometryPass();
|
||||
|
||||
BlendingPass();
|
||||
|
||||
//PostProcessing();
|
||||
|
||||
commands.clear();
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
void Renderer::setCurrentFrameBuffer(const Framebuffer& fb)
|
||||
{
|
||||
|
@ -7,8 +7,8 @@
|
||||
#include "Memory/Framebuffer.h"
|
||||
#include "../Scene/Components.h"
|
||||
#include"../Scene/Scene.h"
|
||||
#include "Graphics/Primitives/DrawCommand.h"
|
||||
#include "Primitives/Camera.h"
|
||||
#include "OpenglAPI.h"
|
||||
|
||||
namespace YoggieEngine {
|
||||
|
||||
@ -20,39 +20,209 @@ namespace YoggieEngine {
|
||||
|
||||
class Renderer {
|
||||
public:
|
||||
Renderer(RendererConfig& config);
|
||||
Renderer();
|
||||
~Renderer();
|
||||
|
||||
|
||||
void Submit(Render3DComponent& renderComponent, TransformComponent& transform); // Collects DrawCommands
|
||||
void Render(Scene&); // Draw to screen (using drawCall structs)
|
||||
|
||||
// Forward pass
|
||||
/*
|
||||
forwardShader.Use();
|
||||
forwardShader.setUniformVec3("Color", renderComponent.color);
|
||||
forwardShader.setUniformMat4("M", transform.LocalTransform);
|
||||
forwardShader.setUniformMat4("V", MainCamera.view);
|
||||
forwardShader.setUniformMat4("P", MainCamera.projection);
|
||||
|
||||
OpenGLApi::DrawTriangles(renderComponent);
|
||||
*/
|
||||
|
||||
void Render(Scene& scene, Camera MainCamera) {
|
||||
|
||||
MainCamera.projection = glm::perspective(glm::radians(65.0f), ((float)width/(float)height), 0.0001f, 1000.0f);
|
||||
glViewport(0, 0, width, height);
|
||||
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, gBuffer);
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
// Render skybox if the scene has one
|
||||
|
||||
SkyboxShader.Use();
|
||||
SkyboxShader.setUniformMat4("projection", MainCamera.projection);
|
||||
SkyboxShader.setUniformMat4("view", glm::mat4(glm::mat3(MainCamera.view)));
|
||||
|
||||
if (!skyboxVAO) {
|
||||
unsigned int VBO;
|
||||
glGenVertexArrays(1, &skyboxVAO);
|
||||
glGenBuffers(1, &VBO);
|
||||
glBindVertexArray(skyboxVAO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, VBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(skyboxVertices), &skyboxVertices, GL_STATIC_DRAW);
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
|
||||
|
||||
}
|
||||
|
||||
OpenGLApi::DrawCubeMap( skyboxVAO, skybox);
|
||||
|
||||
|
||||
|
||||
|
||||
auto renderables = scene.getReg().view<TransformComponent, Render3DComponent>();
|
||||
gBufferShader.Use();
|
||||
for (auto renderable : renderables) {
|
||||
auto entity = Entity(renderable, &scene);
|
||||
auto& renderComponent = entity.GetComponent<Render3DComponent>();
|
||||
auto& transform = entity.GetComponent<TransformComponent>();
|
||||
|
||||
// Geometry pass
|
||||
gBufferShader.setUniformVec3("Color", renderComponent.color);
|
||||
gBufferShader.setUniformMat4("Model", transform.GetTransform());
|
||||
gBufferShader.setUniformMat4("View", MainCamera.view);
|
||||
gBufferShader.setUniformMat4("Projection", MainCamera.projection);
|
||||
OpenGLApi::DrawTriangles(renderComponent);
|
||||
|
||||
|
||||
}
|
||||
|
||||
// Light pass
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer.GetId());
|
||||
lightingPassShader.Use();
|
||||
lightingPassShader.setUniformInt("gPosition", 0);
|
||||
lightingPassShader.setUniformInt("gNormal", 1);
|
||||
lightingPassShader.setUniformInt("gColorSpec", 2);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, gPosition);
|
||||
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, gNormal);
|
||||
|
||||
glActiveTexture(GL_TEXTURE2);
|
||||
glBindTexture(GL_TEXTURE_2D, gColorSpec);
|
||||
|
||||
auto lights = scene.getReg().view<LightComponent, TransformComponent>();
|
||||
unsigned int lightnr = 0;
|
||||
for (auto light : lights) {
|
||||
auto lightComponent = Entity(light, &scene).GetComponent<LightComponent>();
|
||||
auto transformComponent = Entity(light, &scene).GetComponent<TransformComponent>();
|
||||
|
||||
auto name = "lights[" + std::to_string(lightnr) + "]";
|
||||
lightingPassShader.setUniformVec3(name + ".Position",transformComponent.Position );
|
||||
lightingPassShader.setUniformVec3(name + ".Color", lightComponent.Color);
|
||||
|
||||
const float linear = 0.7f;
|
||||
const float quadratic = 1.8f;
|
||||
lightingPassShader.setUniformFloat(name + ".Linear", linear);
|
||||
lightingPassShader.setUniformFloat(name + ".Quadratic", quadratic);
|
||||
|
||||
lightnr++;
|
||||
|
||||
}
|
||||
|
||||
if (quadVAO == 0)
|
||||
{
|
||||
float quadVertices[] = {
|
||||
-1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
|
||||
-1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
|
||||
1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
|
||||
1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
|
||||
};
|
||||
unsigned int quadVBO;
|
||||
// setup plane VAO ;
|
||||
glGenVertexArrays(1, &quadVAO);
|
||||
glGenBuffers(1, &quadVBO);
|
||||
glBindVertexArray(quadVAO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, quadVBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), &quadVertices, GL_STATIC_DRAW);
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
|
||||
}
|
||||
|
||||
glBindVertexArray(quadVAO);
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
glBindVertexArray(0);
|
||||
|
||||
|
||||
// Copy GBuffer
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, gBuffer);
|
||||
glBindFramebuffer(GL_DRAW_BUFFER, m_framebuffer.GetId());
|
||||
glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_DEPTH_BUFFER_BIT, GL_NEAREST);
|
||||
|
||||
|
||||
if (transparentVAO == 0) {
|
||||
unsigned int transparentVBO;
|
||||
float transparentVertices[] = {
|
||||
// positions // texture Coords (swapped y coordinates because texture is flipped upside down)
|
||||
0.0f, 0.5f, 0.0f, 0.0f, 1.0f,
|
||||
0.0f, -0.5f, 0.0f, 0.0f, 0.0f,
|
||||
1.0f, -0.5f, 0.0f, 1.0f, 0.0f,
|
||||
|
||||
0.0f, 0.5f, 0.0f, 0.0f, 1.0f,
|
||||
1.0f, -0.5f, 0.0f, 1.0f, 0.0f,
|
||||
1.0f, 0.5f, 0.0f, 1.0f, 1.0f
|
||||
};
|
||||
|
||||
glGenVertexArrays(1, &transparentVAO);
|
||||
glGenBuffers(1, &transparentVBO);
|
||||
glBindVertexArray(transparentVAO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, transparentVBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(transparentVertices), transparentVertices, GL_STATIC_DRAW);
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
|
||||
glBindVertexArray(0);
|
||||
|
||||
}
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
BlendingShader.Use();
|
||||
glBindVertexArray(transparentVAO);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, grassTexture.GetID());
|
||||
|
||||
BlendingShader.setUniformMat4("V", MainCamera.view);
|
||||
BlendingShader.setUniformMat4("P", MainCamera.projection);
|
||||
for (unsigned int i = 0; i < vegetation.size(); i++) {
|
||||
|
||||
auto translation = glm::translate(glm::mat4(1.0f), vegetation[i]) ;
|
||||
BlendingShader.setUniformMat4("M", translation);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
|
||||
}
|
||||
|
||||
glBindVertexArray(0);
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
void setCurrentFrameBuffer(const Framebuffer& fb);
|
||||
void setClearColor(const glm::vec3& ClearColor);
|
||||
|
||||
void SetMainCamera(const Camera& camera) { MainCamera = camera; }
|
||||
|
||||
Framebuffer& getCurrentFrameBuffer() { return m_framebuffer; }
|
||||
private:
|
||||
void GeometryPass();
|
||||
void ForwardGeometryPass();
|
||||
void SkyboxPass();
|
||||
void lightingPass(Scene& scene);
|
||||
void BlendingPass();
|
||||
void PostProcessing();
|
||||
void CopyGBuffer();
|
||||
|
||||
|
||||
private:
|
||||
Framebuffer m_framebuffer;
|
||||
int width, height;
|
||||
glm::vec3 m_clearColor;
|
||||
bool m_depthTest;
|
||||
std::vector<DrawCommand> commands;
|
||||
Camera MainCamera;
|
||||
|
||||
unsigned int skyboxVAO = 0;
|
||||
CubeMap sky;
|
||||
void CreateGBuffer();
|
||||
|
||||
Shader forwardShader;
|
||||
|
||||
@ -63,8 +233,59 @@ namespace YoggieEngine {
|
||||
Shader SkyboxShader;
|
||||
Shader postProcessingShader;
|
||||
|
||||
|
||||
// blending
|
||||
Shader BlendingShader;
|
||||
CubeMap skybox;
|
||||
Texture grassTexture = Texture("build/Debug/Texture/grass.png");
|
||||
|
||||
unsigned int transparentVAO = 0;
|
||||
unsigned int skyboxVAO = 0;
|
||||
unsigned int quadVAO = 0;
|
||||
float skyboxVertices[36*3]{
|
||||
// positions
|
||||
-1.0f, 1.0f, -1.0f,
|
||||
-1.0f, -1.0f, -1.0f,
|
||||
1.0f, -1.0f, -1.0f,
|
||||
1.0f, -1.0f, -1.0f,
|
||||
1.0f, 1.0f, -1.0f,
|
||||
-1.0f, 1.0f, -1.0f,
|
||||
-1.0f, -1.0f, 1.0f,
|
||||
-1.0f, -1.0f, -1.0f,
|
||||
-1.0f, 1.0f, -1.0f,
|
||||
-1.0f, 1.0f, -1.0f,
|
||||
-1.0f, 1.0f, 1.0f,
|
||||
-1.0f, -1.0f, 1.0f,
|
||||
1.0f, -1.0f, -1.0f,
|
||||
1.0f, -1.0f, 1.0f,
|
||||
1.0f, 1.0f, 1.0f,
|
||||
1.0f, 1.0f, 1.0f,
|
||||
1.0f, 1.0f, -1.0f,
|
||||
1.0f, -1.0f, -1.0f,
|
||||
-1.0f, -1.0f, 1.0f,
|
||||
-1.0f, 1.0f, 1.0f,
|
||||
1.0f, 1.0f, 1.0f,
|
||||
1.0f, 1.0f, 1.0f,
|
||||
1.0f, -1.0f, 1.0f,
|
||||
-1.0f, -1.0f, 1.0f,
|
||||
-1.0f, 1.0f, -1.0f,
|
||||
1.0f, 1.0f, -1.0f,
|
||||
1.0f, 1.0f, 1.0f,
|
||||
1.0f, 1.0f, 1.0f,
|
||||
-1.0f, 1.0f, 1.0f,
|
||||
-1.0f, 1.0f, -1.0f,
|
||||
-1.0f, -1.0f, -1.0f,
|
||||
-1.0f, -1.0f, 1.0f,
|
||||
1.0f, -1.0f, -1.0f,
|
||||
1.0f, -1.0f, -1.0f,
|
||||
-1.0f, -1.0f, 1.0f,
|
||||
1.0f, -1.0f, 1.0f
|
||||
};
|
||||
std::vector<glm::vec3> vegetation = {
|
||||
glm::vec3(-1.5f, 0.0f, -0.48f),
|
||||
glm::vec3(1.5f, 0.0f, 0.51f),
|
||||
glm::vec3(0.0f, 0.0f, 0.7f),
|
||||
glm::vec3(-0.3f, 0.0f, -2.3f)
|
||||
};
|
||||
|
||||
};
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user