Quake maps geometry batching

Rendering Optimization
This commit is contained in:
Antoine Pilote
2021-07-13 22:23:19 -04:00
parent 38ceae6fa9
commit 2b88ee09e3
23 changed files with 347 additions and 266 deletions

View File

@@ -212,7 +212,7 @@ float ShadowCalculation(Light light, vec3 FragPos, vec3 normal)
int shadowmap = -1;
// Get CSM depth
for (int i = 0; i < 4; i++)
for (int i = 0; i < 2; i++)
{
float CSMDepth = light.CascadeDepth[i] ;

View File

@@ -1,20 +1,17 @@
#shader vertex
#version 460 core
layout(location = 0) in vec3 Position;
uniform mat4 lightSpaceMatrix;
uniform mat4 model;
uniform mat4 u_LightTransform;
uniform mat4 u_Model;
void main()
{
gl_Position = lightSpaceMatrix * model * vec4(Position, 1.0);
gl_Position = u_LightTransform * u_Model * vec4(Position, 1.0);
}
#shader fragment
#version 460 core
void main()
{
}
void main() { }

View File

@@ -28,6 +28,7 @@
#include "src/Scene/Components/WrenScriptComponent.h"
#include "src/Scene/Systems/QuakeMapBuilder.h"
#include "src/Scene/Components/LightComponent.h"
#include "UIComponents/Viewport.h"
namespace Nuake {
Ref<UI::UserInterface> userInterface;
@@ -53,7 +54,6 @@ namespace Nuake {
void EditorInterface::DrawViewport()
{
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));
std::string name = ICON_FA_GAMEPAD + std::string(" Scene");
if (ImGui::Begin(name.c_str()))
{
@@ -125,7 +125,6 @@ namespace Nuake {
ImGui::PopStyleVar();
}
ImGui::End();
}
static int selected = 0;

View File

@@ -0,0 +1,21 @@
#include "Viewport.h"
#include <src/Vendors/imgui/imgui.h>
Viewport::Viewport(const std::string& name, Ref<Nuake::Texture> texture)
{
Name = name;
Texture = texture;
}
void Viewport::Draw()
{
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));
if (ImGui::Begin(Name.c_str()))
{
ImGui::Image((void*)Texture->GetID(), ImGui::GetContentRegionAvail(), ImVec2(0, 1), ImVec2(1, 0));
}
ImGui::PopStyleVar();
ImGui::End();
}

View File

@@ -0,0 +1,13 @@
#pragma once
#include "Engine.h"
#include "src/Rendering/Textures/Texture.h"
class Viewport
{
public:
std::string Name = "";
Ref<Nuake::Texture> Texture;
Viewport(const std::string& name, Ref<Nuake::Texture> texture);
void Draw();
};

View File

@@ -58,6 +58,11 @@ namespace Nuake {
glVertexAttribPointer(index, size, glType, normalized, stride, pointer);
}
void OGLRendererAPI::DrawMultiElements(const RendererEnum mode, const int count, const RendererEnum type, const void* const* indices, unsigned int drawCount)
{
glMultiDrawElements(GetType(mode), &count, GetType(type), indices, drawCount);
}
void OGLRendererAPI::DrawElements(const RendererEnum mode, const int count, const RendererEnum type, const void* indices)
{
glDrawElements(GetType(mode), count, GetType(type), indices);

View File

@@ -22,6 +22,7 @@ namespace Nuake {
void EnableVertexAttribArray(unsigned int& index) override;
void VertexAttribPointer(const unsigned int index, const int size, const RendererEnum type, bool normalized, int stride, const void* pointer) override;
void DrawMultiElements(const RendererEnum mode, const int count, const RendererEnum type, const void* const* indices, unsigned int drawCount) override;
void DrawElements(const RendererEnum mode, const int count, const RendererEnum type, const void* indices) override;
void DrawArrays(int from, int count) override;
private:

View File

@@ -27,6 +27,7 @@ namespace Nuake {
virtual void EnableVertexAttribArray(unsigned int& index) = 0;
virtual void VertexAttribPointer(const unsigned int index, const int size, const RendererEnum type, bool normalized, int stride, const void* pointer) = 0;
virtual void DrawMultiElements(const RendererEnum mode, const int count, const RendererEnum type, const void* const* indices, unsigned int drawCount) = 0;
virtual void DrawElements(const RendererEnum mode, const int count, const RendererEnum type, const void* indices) = 0;
virtual void DrawArrays(int from, int count) = 0;
};

View File

@@ -64,6 +64,11 @@ namespace Nuake {
sRendererAPI->VertexAttribPointer(index, size, type, normalized, stride, pointer);
}
void RenderCommand::DrawMultiElements(const RendererEnum mode, const int count, const RendererEnum type, const void* const* indices, unsigned int drawCount)
{
sRendererAPI->DrawMultiElements(mode, count, type, indices, drawCount);
}
void RenderCommand::DrawElements(const RendererEnum mode, const int count, const RendererEnum type, const void* indices)
{
sRendererAPI->DrawElements(mode, count, type, indices);

View File

@@ -26,7 +26,7 @@ namespace Nuake {
static void BindVertexArray(const unsigned int& rendererID);
static void VertexAttribPointer(const unsigned int index, const int size, const RendererEnum type, bool normalized, int stride, const void* pointer);
static void DrawMultiElements(const RendererEnum mode, const int count, const RendererEnum type, const void* const* indices, unsigned int drawCount);
static void DrawElements(const RendererEnum mode, const int count, const RendererEnum type, const void* indices);
static void DrawArrays(int first, int count);
private:

View File

@@ -30,17 +30,17 @@ namespace Nuake
m_RenderList[mesh->m_Material].push_back({mesh, transform});
}
void Flush()
void Flush(Ref<Shader> shader, bool depthOnly = false)
{
Ref<Shader> pbrShader = ShaderManager::GetShader("resources/Shaders/basic.shader");
pbrShader->Bind();
shader->Bind();
for (auto& i : m_RenderList)
{
i.first->Bind();
if(!depthOnly)
i.first->Bind();
for (auto& m : i.second)
{
pbrShader->SetUniformMat4f("u_Model", m.transform);
shader->SetUniformMat4f("u_Model", m.transform);
m.Mesh->Draw(false);
}
}

View File

@@ -95,7 +95,7 @@ namespace Nuake
m_DeferredShader = ShaderManager::GetShader("resources/Shaders/deferred.shader");
m_ProceduralSkyShader = ShaderManager::GetShader("resources/Shaders/atmospheric_sky.shader");
m_DebugShader = ShaderManager::GetShader("resources/Shaders/debug.shader");
m_Shader = ShaderManager::GetShader("resources/Shaders/basic.shader");
m_Shader = ShaderManager::GetShader("resources/Shaders/pbr.shader");
}
void Renderer::SubmitMesh(Ref<Mesh> mesh, Matrix4 transform)
@@ -103,15 +103,13 @@ namespace Nuake
m_RenderList.AddToRenderList(mesh, transform);
}
void Renderer::Flush()
void Renderer::Flush(Ref<Shader> shader, bool depthOnly)
{
m_RenderList.Flush();
m_RenderList.Flush(shader, depthOnly);
}
void Renderer::BeginDraw(Ref<Camera> camera)
{
RenderCommand::Clear();
m_Shader->Bind();
m_Shader->SetUniformMat4f("u_Projection", camera->GetPerspective());
m_Shader->SetUniformMat4f("u_View", camera->GetTransform());
@@ -126,7 +124,7 @@ namespace Nuake
// List of all lights queued to be used for rendering this frame.
std::vector<Light> Renderer::m_Lights;
void Renderer::RegisterLight(TransformComponent transform, LightComponent light, Ref<Camera> cam)
void Renderer::RegisterLight(TransformComponent transform, LightComponent light)
{
if (m_Lights.size() == 20)
return;
@@ -143,26 +141,17 @@ namespace Nuake
if (light.CastShadows)
{
light.m_Framebuffers[0]->GetTexture(GL_DEPTH_ATTACHMENT)->Bind(17);
light.m_Framebuffers[1]->GetTexture(GL_DEPTH_ATTACHMENT)->Bind(18);
light.m_Framebuffers[2]->GetTexture(GL_DEPTH_ATTACHMENT)->Bind(19);
light.m_Framebuffers[3]->GetTexture(GL_DEPTH_ATTACHMENT)->Bind(20);
for (unsigned int i = 0; i < CSM_AMOUNT; i++)
{
light.m_Framebuffers[i]->GetTexture(GL_DEPTH_ATTACHMENT)->Bind(17 + i);
m_Shader->SetUniform1i("Lights[" + std::to_string(idx - 1) + "].ShadowMaps[" + std::to_string(i) + "]", 17 + i);
m_Shader->SetUniform1f("Lights[" + std::to_string(idx - 1) + "].CascadeDepth[" + std::to_string(i) + "]", light.mCascadeSplitDepth[i]);
m_Shader->SetUniformMat4f("Lights[" + std::to_string(idx - 1) + "].LightTransforms[" + std::to_string(i) + "]", light.mViewProjections[i]);
}
}
m_Shader->SetUniform1i("LightCount", idx);
m_Shader->SetUniform1i("Lights[" + std::to_string(idx - 1) + "].Type", light.Type);
m_Shader->SetUniform1i("Lights[" + std::to_string(idx - 1) + "].ShadowMaps[0]", 17);
m_Shader->SetUniform1i("Lights[" + std::to_string(idx - 1) + "].ShadowMaps[1]", 18);
m_Shader->SetUniform1i("Lights[" + std::to_string(idx - 1) + "].ShadowMaps[2]", 19);
m_Shader->SetUniform1i("Lights[" + std::to_string(idx - 1) + "].ShadowMaps[3]", 20);
m_Shader->SetUniformMat4f("Lights[" + std::to_string(idx - 1) + "].LightTransforms[0]", light.mViewProjections[0]);
m_Shader->SetUniformMat4f("Lights[" + std::to_string(idx - 1) + "].LightTransforms[1]", light.mViewProjections[1]);
m_Shader->SetUniformMat4f("Lights[" + std::to_string(idx - 1) + "].LightTransforms[2]", light.mViewProjections[2]);
m_Shader->SetUniformMat4f("Lights[" + std::to_string(idx - 1) + "].LightTransforms[3]", light.mViewProjections[3]);
m_Shader->SetUniform1f("Lights[" + std::to_string(idx - 1) + "].CascadeDepth[0]", light.mCascadeSplitDepth[0]);
m_Shader->SetUniform1f("Lights[" + std::to_string(idx - 1) + "].CascadeDepth[1]", light.mCascadeSplitDepth[1]);
m_Shader->SetUniform1f("Lights[" + std::to_string(idx - 1) + "].CascadeDepth[2]", light.mCascadeSplitDepth[2]);
m_Shader->SetUniform1f("Lights[" + std::to_string(idx - 1) + "].CascadeDepth[3]", light.mCascadeSplitDepth[3]);
m_Shader->SetUniformMat4f("Lights[" + std::to_string(idx - 1) + "].LightTransform", light.GetProjection() * lightView);
m_Shader->SetUniform3f("Lights[" + std::to_string(idx - 1) + "].Position", transform.GlobalTranslation.x, transform.GlobalTranslation.y, transform.GlobalTranslation.z);
m_Shader->SetUniform3f("Lights[" + std::to_string(idx - 1) + "].Direction", direction.x, direction.y, direction.z);

View File

@@ -37,7 +37,7 @@ namespace Nuake
static void BeginScene();
static void SubmitMesh(Ref<Mesh> mesh, Matrix4 transform);
static void Flush();
static void Flush(Ref<Shader> shader, bool depthOnly = false);
// Drawing states
static void BeginDraw(Ref<Camera> camera);
@@ -45,7 +45,7 @@ namespace Nuake
// Lights
static std::vector<Light> m_Lights;
static void RegisterLight(TransformComponent transform, LightComponent light, Ref<Camera> cam);
static void RegisterLight(TransformComponent transform, LightComponent light);
static void RegisterDeferredLight(TransformComponent transform, LightComponent light, Camera* cam);

View File

@@ -130,7 +130,7 @@ namespace Nuake
// Retrieve uniform address and registers it if not already registered.
int Shader::FindUniformLocation(std::string uniform)
{
if (UniformCache.count(uniform) != 0)
if (UniformCache.find(uniform) == UniformCache.end())
{
int addr = glGetUniformLocation(ProgramId, uniform.c_str());

View File

@@ -34,14 +34,14 @@ namespace Nuake {
CastShadows = toggle;
if (CastShadows)
{
for (int i = 0; i < 4; i++)
for (int i = 0; i < CSM_AMOUNT; i++)
{
m_Framebuffers[i] = CreateRef<FrameBuffer>(false, glm::vec2(4096, 4096));
m_Framebuffers[i]->SetTexture(CreateRef<Texture>(glm::vec2(4096, 4096), GL_DEPTH_COMPONENT), GL_DEPTH_ATTACHMENT);
}
}
else {
for (int i = 0; i < 4; i++)
for (int i = 0; i < CSM_AMOUNT; i++)
{
m_Framebuffers[i] = nullptr;
}
@@ -96,7 +96,7 @@ namespace Nuake {
void LightComponent::Draw(TransformComponent transformComponent, Ref<Camera> cam)
{
Renderer::RegisterLight(transformComponent, *this, cam);
}
void LightComponent::DrawDeferred(TransformComponent transformComponent, Camera* cam)

View File

@@ -16,6 +16,7 @@ namespace Nuake
Directional, Point, Spot
};
const int CSM_AMOUNT = 4;
class LightComponent
{
public:
@@ -32,9 +33,9 @@ namespace Nuake
float LinearAttenuation = 0.0f;
float QuadraticAttenuation = 0.0f;
Ref<FrameBuffer> m_Framebuffers[4];
glm::mat4 mViewProjections[4];
float mCascadeSplitDepth[4];
Ref<FrameBuffer> m_Framebuffers[CSM_AMOUNT];
glm::mat4 mViewProjections[CSM_AMOUNT];
float mCascadeSplitDepth[CSM_AMOUNT];
LightComponent();
@@ -57,8 +58,7 @@ namespace Nuake
void SetType(LightType type);
float mCascadeSplits[4];
float mCascadeSplits[CSM_AMOUNT];
void CalculateViewProjection(glm::mat4& view, const glm::mat4& projection)
{
@@ -78,7 +78,7 @@ namespace Nuake
const float maxZ = nearClip + clipRange;
const float range = maxZ - minZ;
const float ratio = maxZ / minZ;
for (int i = 0; i < 4; i++)
for (int i = 0; i < CSM_AMOUNT; i++)
{
const float p = (i + 1) / static_cast<float>(4);
const float log = minZ * glm::pow(ratio, p);
@@ -93,7 +93,7 @@ namespace Nuake
float lastSplitDist = 0.0f;
// Calculate Orthographic Projection matrix for each cascade
for (int cascade = 0; cascade < 4; cascade++)
for (int cascade = 0; cascade < CSM_AMOUNT; cascade++)
{
float splitDist = mCascadeSplits[cascade];
glm::vec4 frustumCorners[8] =
@@ -117,7 +117,7 @@ namespace Nuake
glm::vec4 invCorner = inverseViewProjection * frustumCorners[i];
frustumCorners[i] = invCorner / invCorner.w;
}
for (int i = 0; i < 4; i++)
for (int i = 0; i < CSM_AMOUNT; i++)
{
glm::vec4 dist = frustumCorners[i + 4] - frustumCorners[i];
frustumCorners[i + 4] = frustumCorners[i] + (dist * splitDist);

View File

@@ -21,7 +21,8 @@ namespace Nuake {
m_AmbientColor = color;
}
void Environment::Push() {
void Environment::Push()
{
//Renderer::m_Shader->SetUniform3f("u_AmbientColor", m_AmbientColor.r, m_AmbientColor.g, m_AmbientColor.b);
//Renderer::m_Shader->SetUniform4f("u_AmbientColor", 1.0f, 1.0f, 1.0f, 1.0f);
Renderer::m_Shader->SetUniform1f("u_FogAmount", VolumetricFog);

View File

@@ -163,68 +163,55 @@ namespace Nuake {
auto view = m_Registry.view<TransformComponent, LightComponent>();
Ref<Camera> cam = m_EditorCamera;
if (Engine::IsPlayMode) {
if (Engine::IsPlayMode)
{
auto view = m_Registry.view<TransformComponent, CameraComponent>();
for (auto e : view) {
for (auto e : view)
{
auto [transform, camera] = view.get<TransformComponent, CameraComponent>(e);
cam = camera.CameraInstance;
break;
}
}
glm::mat4 perspective = cam->GetPerspective();
Renderer::m_ShadowmapShader->Bind();
for (auto l : view) {
Ref<Shader> shadowShader = ShaderManager::GetShader("resources/Shaders/shadowMap.shader");
shadowShader->Bind();
for (auto l : view)
{
auto [lightTransform, light] = view.get<TransformComponent, LightComponent>(l);
if (light.Type != LightType::Directional || !light.CastShadows)
continue;
light.CalculateViewProjection(cam->GetTransform(), cam->GetPerspective());
for (int i = 0; i < 4; i++)
for (int i = 0; i < CSM_AMOUNT; i++)
{
light.m_Framebuffers[i]->Bind();
light.m_Framebuffers[i]->Clear();
Renderer::m_ShadowmapShader->SetUniformMat4f("lightSpaceMatrix", light.mViewProjections[i]);
shadowShader->SetUniformMat4f("u_LightTransform", light.mViewProjections[i]);
for (auto e : meshView)
{
auto [transform, mesh] = meshView.get<TransformComponent, MeshComponent>(e);
Renderer::m_ShadowmapShader->SetUniformMat4f("model", transform.GetTransform());
mesh.Draw();
for(auto& m : mesh.meshes)
Renderer::SubmitMesh(m, transform.GetTransform());
}
std::vector<BSPDrawObject> sortedBrushes = std::vector<BSPDrawObject>();
Renderer::m_ShadowmapShader->SetUniformMat4f("lightSpaceMatrix", light.mViewProjections[i]);
auto quakeView = m_Registry.view<TransformComponent, BSPBrushComponent>();
for (auto e : quakeView) {
for (auto e : quakeView)
{
auto [transform, model] = quakeView.get<TransformComponent, BSPBrushComponent>(e);
Renderer::m_ShadowmapShader->SetUniformMat4f("model", transform.GetTransform());
if (model.IsTransparent)
continue;
float dist = glm::length(transform.GlobalTranslation - cam->GetTranslation());
sortedBrushes.push_back({
dist,
model,
transform.GetTransform()
});
//for (auto& e : model.Meshes) {
// e->Draw(false);
//}
for (auto& m : model.Meshes)
Renderer::SubmitMesh(m, transform.GetTransform());
}
std::sort(sortedBrushes.begin(), sortedBrushes.end(), DepthSort);
for (auto& b : sortedBrushes)
{
Renderer::m_ShadowmapShader->SetUniformMat4f("model", b.transform);
for (auto& e : b.brush.Meshes) {
e->Draw(false);
}
}
Renderer::Flush(shadowShader, true);
}
}
@@ -233,13 +220,9 @@ namespace Nuake {
void Scene::DrawInterface(Vector2 screensize)
{
for (auto i : m_Interfaces)
{
i->Draw(screensize);
}
}
void Scene::Draw()
{
// Find the camera of the scene.
@@ -253,98 +236,23 @@ namespace Nuake {
break;
}
}
Ref<Shader> pbrShader = ShaderManager::GetShader("resources/Shaders/pbr.shader");
glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);
Ref<Environment> env = GetEnvironment();
if (env->ProceduralSkybox)
{
env->ProceduralSkybox->Draw(cam);
}
Renderer::m_Shader->Bind();
pbrShader->Bind();
env->Push();
glEnable(GL_DEPTH_TEST);
// Push lights
{
auto view = m_Registry.view<TransformComponent, LightComponent, ParentComponent>();
for (auto l : view) {
auto [transform, light, parent] = view.get<TransformComponent, LightComponent, ParentComponent>(l);
if (light.SyncDirectionWithSky)
light.Direction = GetEnvironment()->ProceduralSkybox->GetSunDirection();
light.Draw(transform, m_EditorCamera);
}
}
glEnable(GL_CULL_FACE);
glCullFace(GL_FRONT);
Renderer::m_Shader->Bind();
Renderer::m_Shader->SetUniform3f("u_EyePosition", cam->GetTranslation().x, cam->GetTranslation().y, cam->GetTranslation().z);
Renderer::m_Shader->SetUniform1i("u_ShowNormal", 0);
if (cam)
{
Renderer::m_Shader->SetUniform1f("u_Exposure", cam->Exposure);
auto view = m_Registry.view<TransformComponent, MeshComponent, ParentComponent>();
for (auto e : view) {
auto [transform, model, parent] = view.get<TransformComponent, MeshComponent, ParentComponent>(e);
Renderer::m_Shader->SetUniformMat4f("u_View", cam->GetTransform());
Renderer::m_Shader->SetUniformMat4f("u_Projection", cam->GetPerspective());
Renderer::m_Shader->SetUniformMat4f("u_Model", transform.GetTransform());
for (auto& m : model.meshes)
{
Renderer::SubmitMesh(m, transform.GetTransform());
}
model.Draw();
}
std::vector<BSPDrawObject> sortedBrushes = std::vector<BSPDrawObject>();
auto quakeView = m_Registry.view<TransformComponent, BSPBrushComponent, ParentComponent>();
for (auto e : quakeView) {
auto [transform, model, parent] = quakeView.get<TransformComponent, BSPBrushComponent, ParentComponent>(e);
if (model.IsTransparent)
continue;
Renderer::m_Shader->SetUniformMat4f("u_View", cam->GetTransform());
Renderer::m_Shader->SetUniformMat4f("u_Projection", cam->GetPerspective());
for (auto& b : model.Meshes)
{
Renderer::m_Shader->SetUniformMat4f("u_Model", transform.GetTransform());
Renderer::SubmitMesh(b, transform.GetTransform());
}
}
Renderer::m_DebugShader->SetUniformMat4f("u_View", cam->GetTransform());
Renderer::m_DebugShader->SetUniformMat4f("u_Projection", cam->GetPerspective());
Renderer::Flush();
PhysicsManager::Get()->DrawDebug();
}
}
void Scene::EditorDraw()
{
glDisable(GL_DEPTH_TEST);
Ref<Environment> env = GetEnvironment();
glDisable(GL_CULL_FACE);
if (env->ProceduralSkybox)
env->ProceduralSkybox->Draw(m_EditorCamera);
Renderer::m_Shader->Bind();
env->Push();
glEnable(GL_DEPTH_TEST);
// Register the lights
auto view = m_Registry.view<TransformComponent, LightComponent, ParentComponent>();
for (auto l : view)
{
@@ -353,26 +261,87 @@ namespace Nuake {
if (light.SyncDirectionWithSky)
light.Direction = GetEnvironment()->ProceduralSkybox->GetSunDirection();
light.Draw(transform, m_EditorCamera);
Renderer::RegisterLight(transform, light);
}
pbrShader->SetUniform3f("u_EyePosition", cam->GetTranslation().x, cam->GetTranslation().y, cam->GetTranslation().z);
pbrShader->SetUniform1i("u_ShowNormal", 0);
if (cam)
{
pbrShader->SetUniform1f("u_Exposure", cam->Exposure);
pbrShader->SetUniformMat4f("u_View", cam->GetTransform());
pbrShader->SetUniformMat4f("u_Projection", cam->GetPerspective());
auto view = m_Registry.view<TransformComponent, MeshComponent, ParentComponent>();
for (auto e : view)
{
auto [transform, model, parent] = view.get<TransformComponent, MeshComponent, ParentComponent>(e);
for (auto& m : model.meshes)
Renderer::SubmitMesh(m, transform.GetTransform());
}
auto quakeView = m_Registry.view<TransformComponent, BSPBrushComponent, ParentComponent>();
for (auto e : quakeView)
{
auto [transform, model, parent] = quakeView.get<TransformComponent, BSPBrushComponent, ParentComponent>(e);
if (model.IsTransparent)
continue;
for (auto& b : model.Meshes)
Renderer::SubmitMesh(b, transform.GetTransform());
}
Renderer::Flush(pbrShader);
PhysicsManager::Get()->DrawDebug();
}
}
void Scene::EditorDraw()
{
Ref<Environment> env = GetEnvironment();
glDisable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
if (env->ProceduralSkybox)
env->ProceduralSkybox->Draw(m_EditorCamera);
glEnable(GL_CULL_FACE);
Ref<Shader> pbrShader = ShaderManager::GetShader("resources/Shaders/pbr.shader");
pbrShader->Bind();
env->Push();
glCullFace(GL_FRONT);
Renderer::m_Shader->Bind();
Renderer::m_Shader->SetUniform1i("u_ShowNormal", 0);
glEnable(GL_DEPTH_TEST);
// Register the lights
auto view = m_Registry.view<TransformComponent, LightComponent, ParentComponent>();
for (auto l : view)
{
auto [transform, light, parent] = view.get<TransformComponent, LightComponent, ParentComponent>(l);
if (light.SyncDirectionWithSky)
light.Direction = GetEnvironment()->ProceduralSkybox->GetSunDirection();
Renderer::RegisterLight(transform, light);
}
pbrShader->SetUniform1i("u_ShowNormal", 0);
if (m_EditorCamera)
{
Renderer::m_Shader->SetUniform1f("u_Exposure", m_EditorCamera->Exposure);
Renderer::m_Shader->SetUniform3f("u_EyePosition", m_EditorCamera->GetTranslation().x, m_EditorCamera->GetTranslation().y, m_EditorCamera->GetTranslation().z);
Renderer::m_Shader->SetUniformMat4f("u_View", m_EditorCamera->GetTransform());
Renderer::m_Shader->SetUniformMat4f("u_Projection", m_EditorCamera->GetPerspective());
auto view = m_Registry.view<TransformComponent, MeshComponent, ParentComponent>();
for (auto e : view)
{
auto [transform, mesh, parent] = view.get<TransformComponent, MeshComponent, ParentComponent>(e);
Renderer::m_Shader->SetUniformMat4f("u_View", m_EditorCamera->GetTransform());
Renderer::m_Shader->SetUniformMat4f("u_Projection", m_EditorCamera->GetPerspective());
Renderer::m_Shader->SetUniformMat4f("u_Model", transform.GetTransform());
for(auto& m : mesh.meshes)
Renderer::SubmitMesh(m, transform.GetTransform());
}
@@ -387,20 +356,19 @@ namespace Nuake {
for (auto& b : model.Meshes)
Renderer::SubmitMesh(b, transform.GetTransform());
Renderer::m_Shader->SetUniformMat4f("u_View", m_EditorCamera->GetTransform());
Renderer::m_Shader->SetUniformMat4f("u_Projection", m_EditorCamera->GetPerspective());
}
Renderer::m_DebugShader->Bind();
Renderer::Flush(pbrShader);
Ref<Shader> flatShader = ShaderManager::GetShader("resources/Shaders/flat.shader");
flatShader->Bind();
flatShader->SetUniformMat4f("u_View", m_EditorCamera->GetTransform());
flatShader->SetUniformMat4f("u_Projection", m_EditorCamera->GetPerspective());
auto boxCollider = m_Registry.view<TransformComponent, BoxColliderComponent, ParentComponent>();
for (auto e : boxCollider)
{
auto [transform, box, parent] = boxCollider.get<TransformComponent, BoxColliderComponent, ParentComponent>(e);
Renderer::m_DebugShader->SetUniformMat4f("u_View", m_EditorCamera->GetTransform());
Renderer::m_DebugShader->SetUniformMat4f("u_Projection", m_EditorCamera->GetPerspective());
Renderer::m_DebugShader->SetUniformMat4f("u_Model", transform.GetTransform());
TransformComponent t = transform;
t.Scale = (box.Size * 2.f) * transform.Scale;
@@ -412,17 +380,13 @@ namespace Nuake {
{
auto [transform, box, parent] = sphereCollider.get<TransformComponent, SphereColliderComponent, ParentComponent>(e);
Renderer::m_DebugShader->SetUniformMat4f("u_View", m_EditorCamera->GetTransform());
Renderer::m_DebugShader->SetUniformMat4f("u_Projection", m_EditorCamera->GetPerspective());
Renderer::m_DebugShader->SetUniformMat4f("u_Model", transform.GetTransform());
flatShader->SetUniformMat4f("u_Model", transform.GetTransform());
TransformComponent t = transform;
t.Scale = (box.Radius * 2.f) * transform.Scale;
Renderer::DrawSphere(t, glm::vec4(0.0f, 0.0f, 0.9f, 0.2f));
}
Renderer::m_DebugShader->Bind();
auto quakeViewTransparent = m_Registry.view<TransformComponent, BSPBrushComponent, ParentComponent>();
for (auto e : quakeViewTransparent)
{
@@ -431,16 +395,15 @@ namespace Nuake {
if (!model.IsTransparent)
continue;
Renderer::m_DebugShader->SetUniformMat4f("u_View", m_EditorCamera->GetTransform());
Renderer::m_DebugShader->SetUniformMat4f("u_Projection", m_EditorCamera->GetPerspective());
Renderer::m_DebugShader->SetUniformMat4f("u_Model", transform.GetTransform());
Renderer::m_DebugShader->SetUniform4f("u_Color", 1.f, 0.0f, 0.1f, 0.5f);
flatShader->SetUniformMat4f("u_Model", transform.GetTransform());
flatShader->SetUniform4f("u_Color", 1.f, 0.0f, 0.1f, 0.5f);
for (auto& e : model.Meshes)
Renderer::SubmitMesh(e, transform.GetTransform());
}
Renderer::Flush();
Renderer::Flush(flatShader);
}
}

View File

@@ -6,7 +6,7 @@
#include "src/Scene/Components/QuakeMap.h"
#include "src/Scene/Components/ParentComponent.h"
#include <vector>
#include <map>
extern "C" {
#include <libmap/h/map_parser.h>
@@ -24,6 +24,13 @@ extern "C" {
#include "src/Scene/Components/WrenScriptComponent.h"
namespace Nuake {
struct ProcessedMesh
{
std::vector<Vertex> Vertices;
std::vector<unsigned int> Indices;
};
Ref<Material> DefaultMaterial;
void QuakeMapBuilder::CreateTrigger(brush* brush, brush_geometry* brush_inst,
@@ -131,7 +138,7 @@ namespace Nuake {
for (int i = 0; i < face_geo_inst->vertex_count; ++i)
{
face_vertex vertex = face_geo_inst->vertices[i];
vertex_uv vertex_uv = get_standard_uv(vertex.vertex, face, texture->width, texture->height);
vertex_uv vertex_uv = get_valve_uv(vertex.vertex, face, texture->width, texture->height);
Vector3 vertexPos = Vector3(
(vertex.vertex.y - brush->center.y) * (1.0f / 64),
@@ -139,7 +146,7 @@ namespace Nuake {
(vertex.vertex.x - brush->center.x) * (1.0f / 64)
);
Vector2 vertexUV = Vector2(vertex_uv.u, 1.0 - vertex_uv.v);
Vector2 vertexUV = Vector2(vertex_uv.u, vertex_uv.v);
Vector3 vertexNormal = Vector3(vertex.normal.y, vertex.normal.z, vertex.normal.x);
Vector3 vertexTangent = Vector3(vertex.tangent.y, vertex.tangent.z, vertex.tangent.x);
@@ -149,7 +156,7 @@ namespace Nuake {
vertexNormal,
vertexTangent,
glm::vec3(0.0, 1.0, 0.0), 0.0f
});
});
}
for (int i = 0; i < (face_geo_inst->vertex_count - 2) * 3; ++i)
@@ -228,7 +235,6 @@ namespace Nuake {
int lastTextureID = -1;
std::string lastTexturePath = "";
for (int f = 0; f < brush->face_count; ++f)
{
face* face = &brush->faces[f];
@@ -251,7 +257,7 @@ namespace Nuake {
for (int i = 0; i < face_geo_inst->vertex_count; ++i)
{
face_vertex vertex = face_geo_inst->vertices[i];
vertex_uv vertex_uv = get_standard_uv(vertex.vertex, face, texture->width, texture->height);
vertex_uv vertex_uv = get_valve_uv(vertex.vertex, face, texture->width, texture->height);
Vector3 vertexPos = Vector3(
(vertex.vertex.y - brush->center.y) * (1.0f / 64),
@@ -259,7 +265,7 @@ namespace Nuake {
(vertex.vertex.x - brush->center.x) * (1.0f / 64)
);
Vector2 vertexUV = Vector2(vertex_uv.u, 1.0 - vertex_uv.v);
Vector2 vertexUV = Vector2(vertex_uv.u, vertex_uv.v);
Vector3 vertexNormal = Vector3(vertex.normal.y, vertex.normal.z, vertex.normal.x);
Vector3 vertexTangent = Vector3(vertex.tangent.y, vertex.tangent.z, vertex.tangent.x);
@@ -358,6 +364,7 @@ namespace Nuake {
std::string targetname = "";
FGDBrushEntity fgdBrush;
bool isEntity = false;
bool isWorldSpawn = false;
for (int i = 0; i < entity_inst->property_count; i++)
{
property* prop = &(entity_inst->properties)[i];
@@ -367,12 +374,11 @@ namespace Nuake {
if (key == "origin")
{
std::vector<std::string> splits = String::Split(value, ' ');
float x = String::ToFloat(splits[1]);
float y = String::ToFloat(splits[2]);
float z = String::ToFloat(splits[0]);
float x = String::ToFloat(splits[1]) * (1.f / 64.f);
float y = String::ToFloat(splits[2]) * (1.f / 64.f);
float z = String::ToFloat(splits[0]) * (1.f / 64.f);
Vector3 position = Vector3(x, y, z);
Vector3 position = Vector3(x, y, z) * SCALE_FACTOR;
newEntity.GetComponent<TransformComponent>().Translation = position;
}
@@ -385,33 +391,145 @@ namespace Nuake {
if (type == EntityType::Brush)
{
fgdBrush = file->GetBrushEntity(value);
isEntity = true;
if(fgdBrush.Name != "")
isEntity = true;
else
isWorldSpawn = true;
}
}
else
{
isWorldSpawn = true;
continue;
}
}
if (key == "targetname")
{
targetname = value;
}
if (key == "target")
{
target = value;
}
}
for (int b = 0; b < entity_inst->brush_count; ++b)
if (!isWorldSpawn)
{
brush* brush_inst = &entity_inst->brushes[b];
brush_geometry* brush_geo_inst = &entity_geo_inst->brushes[b];
if (isEntity)
for (int b = 0; b < entity_inst->brush_count; ++b)
{
CreateFuncBrush(brush_inst, brush_geo_inst, m_Scene, newEntity, target, targetname, fgdBrush);
}
else
{
CreateBrush(brush_inst, brush_geo_inst, m_Scene, newEntity, target, targetname);
brush* brush_inst = &entity_inst->brushes[b];
brush_geometry* brush_geo_inst = &entity_geo_inst->brushes[b];
if (isEntity)
CreateFuncBrush(brush_inst, brush_geo_inst, m_Scene, newEntity, target, targetname, fgdBrush);
else
CreateBrush(brush_inst, brush_geo_inst, m_Scene, newEntity, target, targetname);
}
}
else
{
std::map<std::string, Ref<Material>> m_Materials;
std::map<Ref<Material>, std::vector<ProcessedMesh>> m_StaticWorld;
Entity brushEntity = m_Scene->CreateEntity("WorldSpawn");
newEntity.AddChild(brushEntity);
TransformComponent& transformComponent = brushEntity.GetComponent<TransformComponent>();
BSPBrushComponent& bsp = brushEntity.AddComponent<BSPBrushComponent>();
bsp.IsSolid = true;
bsp.IsTransparent = false;
bsp.IsFunc = false;
bsp.IsTrigger = false;
bsp.target = target;
for (int b = 0; b < entity_inst->brush_count; ++b)
{
brush* brush_inst = &entity_inst->brushes[b];
brush_geometry* brush_geo_inst = &entity_geo_inst->brushes[b];
for (int f = 0; f < brush_inst->face_count; ++f)
{
face* face = &brush_inst->faces[f];
texture_data* texture = &textures[face->texture_idx];
Ref<Material> currentMaterial;
if (std::string(texture->name) != "__TB_empty")
{
std::string path = FileSystem::Root + "Textures/" + std::string(texture->name) + ".png";
if (m_Materials.find(path) == m_Materials.end())
m_Materials[path] = MaterialManager::Get()->GetMaterial(path);
currentMaterial = m_Materials[path];
texture->height = currentMaterial->m_Albedo->GetHeight();
texture->width = currentMaterial->m_Albedo->GetWidth();
}
else
{
currentMaterial = MaterialManager::Get()->GetMaterial("resources/Textures/default/Default.png");
texture->height = texture->width = 1;
}
face_geometry* face_geo_inst = &brush_geo_inst->faces[f];
std::vector<Vertex> vertices;
std::vector<unsigned int> indices;
for (int i = 0; i < face_geo_inst->vertex_count; ++i)
{
face_vertex vertex = face_geo_inst->vertices[i];
vertex_uv vertex_uv = get_valve_uv(vertex.vertex, face, texture->width, texture->height);
Vector3 vertexPos = Vector3(
vertex.vertex.y,
vertex.vertex.z,
vertex.vertex.x
);
Vector2 vertexUV = Vector2(vertex_uv.u, 1.0 - vertex_uv.v);
Vector3 vertexNormal = Vector3(vertex.normal.y, vertex.normal.z, vertex.normal.x);
Vector3 vertexTangent = Vector3(vertex.tangent.y, vertex.tangent.z, vertex.tangent.x);
Vector3 vertexBitangent = glm::cross(vertexNormal, vertexTangent) * (float)vertex.tangent.w;
vertices.push_back(Vertex {
vertexPos * SCALE_FACTOR,
vertexUV,
vertexNormal,
vertexTangent,
vertexBitangent,
0.0f
});
}
for (int i = 0; i < (face_geo_inst->vertex_count - 2) * 3; ++i)
{
unsigned int index = face_geo_inst->indices[i];
indices.push_back((unsigned int)index);
}
m_StaticWorld[currentMaterial].push_back({vertices, indices});
vertices.clear();
indices.clear();
}
}
// Batching process
for (auto& mat : m_StaticWorld)
{
std::vector<Vertex> batchedVertices;
std::vector<unsigned int> batchedIndices;
int indexOffset = 0;
for (auto& pm : mat.second)
{
for(auto& vert : pm.Vertices)
batchedVertices.push_back(vert);
for (auto& index : pm.Indices)
batchedIndices.push_back(indexOffset + index);
indexOffset += pm.Vertices.size();
}
bsp.Meshes.push_back(CreateRef<Mesh>(batchedVertices, batchedIndices, mat.first));
}
}
isEntity = false;
}
}

View File

@@ -12,6 +12,7 @@ namespace Nuake {
class QuakeMapBuilder
{
private:
const float SCALE_FACTOR = 1.f / 64.f;
void CreateTrigger(brush* brush, brush_geometry* brush_inst,
Scene* scene, Entity& parent,
const std::string& target, const std::string& targetname);
@@ -23,6 +24,7 @@ namespace Nuake {
void CreateFuncBrush(brush* brush, brush_geometry* brush_inst,
Scene* scene, Entity& parent,
const std::string& target, const std::string& targetname, FGDBrushEntity fgdBrush);
public:
QuakeMapBuilder() {}

View File

@@ -218,41 +218,7 @@ void generate_brush_vertices(int entity_idx, int brush_idx)
face *face_inst = &entities[entity_idx].brushes[brush_idx].faces[f0];
face_geometry *face_geo_inst = &entity_geo[entity_idx].brushes[brush_idx].faces[f0];
vec3 normal;
const char *phong_property = map_data_get_entity_property(entity_idx, "_phong");
bool phong = phong_property != NULL && strcmp(phong_property, "1") == 0;
if (phong)
{
const char *phong_angle_property = map_data_get_entity_property(entity_idx, "_phong_angle");
if (phong_angle_property != NULL)
{
double threshold = cos((atof(phong_angle_property) + 0.01) * 0.0174533);
normal = brush_inst->faces[f0].plane_normal;
if (vec3_dot(brush_inst->faces[f0].plane_normal, brush_inst->faces[f1].plane_normal) > threshold)
{
normal = vec3_add(normal, brush_inst->faces[f1].plane_normal);
}
if (vec3_dot(brush_inst->faces[f0].plane_normal, brush_inst->faces[f2].plane_normal) > threshold)
{
normal = vec3_add(normal, brush_inst->faces[f2].plane_normal);
}
normal = vec3_normalize(normal);
}
else
{
normal = vec3_normalize(
vec3_add(
brush_inst->faces[f0].plane_normal,
vec3_add(
brush_inst->faces[f1].plane_normal,
brush_inst->faces[f2].plane_normal)));
}
}
else
{
normal = face_inst->plane_normal;
}
vec3 normal = face_inst->plane_normal;
texture_data *texture = map_data_get_texture(face_inst->texture_idx);
@@ -296,10 +262,10 @@ void generate_brush_vertices(int entity_idx, int brush_idx)
face_geo_inst->vertices = realloc(face_geo_inst->vertices, face_geo_inst->vertex_count * sizeof(face_vertex));
face_geo_inst->vertices[face_geo_inst->vertex_count - 1] = (face_vertex){vertex, normal, uv, tangent};
}
else if(phong)
{
face_geo_inst->vertices[duplicate_index].normal = vec3_add(face_geo_inst->vertices[duplicate_index].normal, normal);
}
//else if(phong)
//{
// face_geo_inst->vertices[duplicate_index].normal = vec3_add(face_geo_inst->vertices[duplicate_index].normal, normal);
//}
}
}

View File

@@ -226,19 +226,19 @@ namespace Nuake {
void Window::Draw()
{
// Dont render if no scene is loaded.
if (!m_Scene)
return;
// Dont render if no cam is found.
Ref<Camera> cam = m_Scene->GetCurrentCamera();
if (!cam) return;
if (!cam)
return;
Vector2 size = m_Framebuffer->GetSize();
cam->AspectRatio = size.x / size.y;
Renderer::BeginDraw(cam);
//Renderer::BeginDraw(cam);
m_Scene->DrawShadows();