445 lines
17 KiB
C++
445 lines
17 KiB
C++
#include "Renderer.h"
|
|
|
|
#include <glad/glad.h>
|
|
|
|
#include "RenderCommand.h"
|
|
|
|
#include "src/Rendering/Camera.h"
|
|
#include "src/Rendering/Textures/Texture.h"
|
|
#include "src/Rendering/Textures/Cubemap.h"
|
|
#include "src/Rendering/Shaders/ShaderManager.h"
|
|
#include "Engine.h"
|
|
#include "src/Core/Core.h"
|
|
#include "src/Core/Maths.h"
|
|
|
|
#include <glm/gtc/type_ptr.hpp>
|
|
#include "Buffers/VertexBufferLayout.h"
|
|
#include "src/Rendering/Textures/MaterialManager.h"
|
|
#include "src/Rendering/Vertex.h"
|
|
#include <imgui/imgui.h>
|
|
#include <Tracy.hpp>
|
|
#include <vector>
|
|
namespace Nuake
|
|
{
|
|
uint32_t Renderer::MAX_LIGHT = 42;
|
|
|
|
unsigned int depthTexture;
|
|
unsigned int depthFBO;
|
|
|
|
Ref<Mesh> Renderer::CubeMesh;
|
|
Ref<Mesh> Renderer::QuadMesh;
|
|
Ref<Mesh> Renderer::SphereMesh;
|
|
|
|
Shader* Renderer::m_Shader;
|
|
Shader* Renderer::m_SkyboxShader;
|
|
Shader* Renderer::m_BRDShader;
|
|
Shader* Renderer::m_GBufferShader;
|
|
Shader* Renderer::m_DeferredShader;
|
|
Shader* Renderer::m_ProceduralSkyShader;
|
|
Shader* Renderer::m_DebugShader;
|
|
Shader* Renderer::m_ShadowmapShader;
|
|
|
|
VertexArray* Renderer::QuadVertexArray;
|
|
VertexBuffer* Renderer::QuadVertexBuffer;
|
|
VertexArray* Renderer::CubeVertexArray;
|
|
VertexBuffer* Renderer::CubeVertexBuffer;
|
|
|
|
Ref<UniformBuffer> Renderer::m_LightsUniformBuffer;
|
|
RenderList Renderer::m_RenderList = RenderList();
|
|
|
|
std::vector<Vertex> CubeVertices
|
|
{
|
|
{ Vector3(-1.0f, 1.0f, -1.0f), Vector2(0, 0), Vector3(-1, 0, 0) },
|
|
{ Vector3(-1.0f, -1.0f, -1.0f), Vector2(1, 0), Vector3(-1,-1, 0) },
|
|
{ Vector3(1.0f, -1.0f, -1.0f), Vector2(0, 1), Vector3(-1, 0, 0) },
|
|
{ Vector3(1.0f, -1.0f, -1.0f), Vector2(1, 1), Vector3(-1, 0, 0) },
|
|
{ Vector3(1.0f, 1.0f, -1.0f), Vector2(0, 1), Vector3(-1, 0, 0) },
|
|
{ Vector3(-1.0f, 1.0f, -1.0f), Vector2(1, 0), Vector3(-1, 0, 0) },
|
|
{ Vector3(-1.0f, -1.0f, 1.0f), Vector2(1, 1), Vector3(-1, 0, 0) },
|
|
{ Vector3(-1.0f, -1.0f, -1.0f), Vector2(1, 1), Vector3(-1, 0, 0) },
|
|
{ Vector3(-1.0f, 1.0f, -1.0f), Vector2(0, 0), Vector3(-1, 0, 0) },
|
|
{ Vector3(-1.0f, 1.0f, -1.0f), Vector2(1, 0), Vector3(-1,-1, 0) },
|
|
{ Vector3(-1.0f, 1.0f, 1.0f), Vector2(0, 1), Vector3(-1, 0, 0) },
|
|
{ Vector3(-1.0f, -1.0f, 1.0f), Vector2(1, 1), Vector3(-1, 0, 0) },
|
|
{ Vector3(1.0f, -1.0f, -1.0f), Vector2(0, 1), Vector3(-1, 0, 0) },
|
|
{ Vector3(1.0f, -1.0f, 1.0f), Vector2(1, 0), Vector3(-1, 0, 0) },
|
|
{ Vector3(1.0f, 1.0f, 1.0f), Vector2(1, 1), Vector3(-1, 0, 0) },
|
|
{ Vector3(1.0f, 1.0f, 1.0f), Vector2(1, 1), Vector3(-1, 0, 0) },
|
|
{ Vector3(1.0f, 1.0f, -1.0f), Vector2(0, 0), Vector3(-1, 0, 0) },
|
|
{ Vector3(1.0f, -1.0f, -1.0f), Vector2(1, 0), Vector3(-1,-1, 0) },
|
|
{ Vector3(-1.0f, -1.0f, 1.0f), Vector2(0, 1), Vector3(-1, 0, 0) },
|
|
{ Vector3(-1.0f, 1.0f, 1.0f), Vector2(1, 1), Vector3(-1, 0, 0) },
|
|
{ Vector3(1.0f, 1.0f, 1.0f), Vector2(0, 1), Vector3(-1, 0, 0) },
|
|
{ Vector3(1.0f, 1.0f, 1.0f), Vector2(1, 0), Vector3(-1, 0, 0) },
|
|
{ Vector3(1.0f, -1.0f, 1.0f), Vector2(1, 1), Vector3(-1, 0, 0) },
|
|
{ Vector3(-1.0f, -1.0f, 1.0f), Vector2(1, 1), Vector3(-1, 0, 0) },
|
|
{ Vector3(-1.0f, 1.0f, -1.0f), Vector2(0, 0), Vector3(-1, 0, 0) },
|
|
{ Vector3(1.0f, 1.0f, -1.0f), Vector2(1, 0), Vector3(-1,-1, 0) },
|
|
{ Vector3(1.0f, 1.0f, 1.0f), Vector2(0, 1), Vector3(-1, 0, 0) },
|
|
{ Vector3(1.0f, 1.0f, 1.0f), Vector2(1, 1), Vector3(-1, 0, 0) },
|
|
{ Vector3(-1.0f, 1.0f, 1.0f), Vector2(0, 1), Vector3(-1, 0, 0) },
|
|
{ Vector3(-1.0f, 1.0f, -1.0f), Vector2(1, 0), Vector3(-1, 0, 0) },
|
|
{ Vector3(-1.0f, -1.0f, -1.0f), Vector2(1, 1), Vector3(-1, 0, 0) },
|
|
{ Vector3(-1.0f, -1.0f, 1.0f), Vector2(1, 1), Vector3(-1, 0, 0) },
|
|
{ Vector3(1.0f, -1.0f, -1.0f), Vector2(0, 0), Vector3(-1, 0, 0) },
|
|
{ Vector3(1.0f, -1.0f, -1.0f), Vector2(1, 0), Vector3(-1,-1, 0) },
|
|
{ Vector3(-1.0f, -1.0f, 1.0f), Vector2(0, 1), Vector3(-1, 0, 0) },
|
|
{ Vector3(1.0f, -1.0f, 1.0f), Vector2(1, 1), Vector3(-1, 0, 0) }
|
|
};
|
|
|
|
std::vector<uint32_t> CubeIndices;
|
|
|
|
std::vector<Vertex> QuadVertices
|
|
{
|
|
{ Vector3(-1.0f, 1.0f, 0.0f), Vector2(0.0f, 1.0f), Vector3(0, 0, 1), Vector3(1, 0, 0), Vector3(0, 1, 0) },
|
|
{ Vector3(1.0f, 1.0f, 0.0f), Vector2(1.0f, 1.0f), Vector3(0, 0, 1), Vector3(1, 0, 0), Vector3(0, 1, 0) },
|
|
{ Vector3(-1.0f, -1.0f, 0.0f), Vector2(0, 0), Vector3(0, 0, 1), Vector3(1, 0, 0), Vector3(0, 1, 0) },
|
|
{ Vector3(1.0f, -1.0f, 0.0f), Vector2(1.0f, 0.0f), Vector3(0, 0, 1), Vector3(1, 0, 0), Vector3(0, 1, 0) },
|
|
{ Vector3(-1.0f, -1.0f, 0.0f), Vector2(0.0f, 0.0f), Vector3(0, 0, 1), Vector3(1, 0, 0), Vector3(0, 1, 0) },
|
|
{ Vector3(1.0f, 1.0f, 0.0f), Vector2(1.0f, 1.0f), Vector3(0, 0, 1), Vector3(1, 0, 0), Vector3(0, 1, 0) }
|
|
};
|
|
|
|
|
|
void Renderer::Init()
|
|
{
|
|
RenderCommand::SetRendererAPI(RendererPlatforms::Vulkan);
|
|
|
|
ShaderManager::LoadShaders();
|
|
|
|
m_LightsUniformBuffer = CreateRef<UniformBuffer>(128);
|
|
|
|
Ref<Material> defaultMaterial = CreateRef<Material>(Vector3{1, 1, 1});
|
|
defaultMaterial->SetName("white");
|
|
MaterialManager::Get()->RegisterMaterial(defaultMaterial);
|
|
|
|
CubeIndices.reserve(36);
|
|
for (int i = 0; i < 36; i++)
|
|
{
|
|
CubeIndices.push_back(i);
|
|
}
|
|
|
|
CubeMesh = CreateRef<Mesh>();
|
|
CubeMesh->AddSurface(CubeVertices, CubeIndices);
|
|
CubeMesh->SetMaterial(defaultMaterial);
|
|
|
|
QuadMesh = CreateRef<Mesh>();
|
|
QuadMesh->AddSurface(QuadVertices, { 0, 1, 2, 3, 4, 5 });
|
|
QuadMesh->SetMaterial(defaultMaterial);
|
|
|
|
SphereMesh = CreateSphereMesh();
|
|
}
|
|
|
|
void Renderer::LoadShaders()
|
|
{
|
|
|
|
}
|
|
|
|
void Renderer::SubmitMesh(Ref<Mesh> mesh, const Matrix4& transform, const int32_t entityId, const Matrix4& previousTransform)
|
|
{
|
|
m_RenderList.AddToRenderList(mesh, transform, entityId, previousTransform);
|
|
}
|
|
|
|
void Renderer::SubmitCube(Matrix4 transform)
|
|
{
|
|
m_RenderList.AddToRenderList(CubeMesh, transform, -1);
|
|
}
|
|
|
|
void Renderer::Flush(Shader* shader, bool depthOnly)
|
|
{
|
|
m_RenderList.Flush(shader, depthOnly);
|
|
}
|
|
|
|
Vector3 ComputeFaceNormal(Vector3 a, Vector3 b, Vector3 c)
|
|
{
|
|
const float EPSILON = 0.000001f;
|
|
|
|
Vector3 normal; // default return value (0,0,0)
|
|
float nx, ny, nz;
|
|
|
|
// find 2 edge vectors: v1-v2, v1-v3
|
|
float ex1 = b.x - a.x;
|
|
float ey1 = b.y - a.y;
|
|
float ez1 = b.z - a.z;
|
|
float ex2 = c.x - a.x;
|
|
float ey2 = c.y - a.y;
|
|
float ez2 = c.z - a.z;
|
|
|
|
// cross product: e1 x e2
|
|
nx = ez1 * ey2 - ey1 * ez2;
|
|
ny = ex1 * ez2 - ez1 * ex2;
|
|
nz = ey1 * ex2 - ex1 * ey2;
|
|
|
|
// normalize only if the length is > 0
|
|
float length = sqrtf(nx * nx + ny * ny + nz * nz);
|
|
if (length > EPSILON)
|
|
{
|
|
// normalize
|
|
float lengthInv = 1.0f / length;
|
|
normal.x = nx * lengthInv;
|
|
normal.y = ny * lengthInv;
|
|
normal.z = nz * lengthInv;
|
|
}
|
|
|
|
return normal * -1.0f;
|
|
}
|
|
|
|
Ref<Mesh> Renderer::CreateSphereMesh()
|
|
{
|
|
const float sectorCount = 36;
|
|
const float stackCount = 36;
|
|
const float radius = 0.5f;
|
|
const float PI = acos(-1.0f);
|
|
|
|
// new
|
|
std::vector<Vertex> finalVertices;
|
|
|
|
float x, y, z, xy; // vertex position
|
|
float nx, ny, nz, lengthInv = 1.0f / radius; // normal
|
|
float s, t; // texCoord
|
|
|
|
float sectorStep = 2 * PI / sectorCount;
|
|
float stackStep = PI / stackCount;
|
|
float sectorAngle, stackAngle;
|
|
|
|
for (int i = 0; i <= stackCount; ++i)
|
|
{
|
|
stackAngle = PI / 2 - i * stackStep; // starting from pi/2 to -pi/2
|
|
xy = radius * cosf(stackAngle); // r * cos(u)
|
|
z = radius * sinf(stackAngle); // r * sin(u)
|
|
|
|
// add (sectorCount+1) vertices per stack
|
|
// the first and last vertices have same position and normal, but different tex coords
|
|
for (int j = 0; j <= sectorCount; ++j)
|
|
{
|
|
sectorAngle = j * sectorStep; // starting from 0 to 2pi
|
|
|
|
Vertex newVertex;
|
|
|
|
x = xy * cosf(sectorAngle); // r * cos(u) * cos(v)
|
|
y = xy * sinf(sectorAngle); // r * cos(u) * sin(v)
|
|
newVertex.position = Vector3(x, y, z);
|
|
|
|
nx = x * lengthInv;
|
|
ny = y * lengthInv;
|
|
nz = z * lengthInv;
|
|
newVertex.normal = Vector3(nx, ny, nz) * -1.0f;
|
|
// vertex position
|
|
|
|
s = (float)j / sectorCount * 4.f;
|
|
t = (float)i / stackCount * 4.f;
|
|
newVertex.uv = { t, s };
|
|
|
|
finalVertices.push_back(newVertex);
|
|
}
|
|
}
|
|
|
|
std::vector<uint32_t> finalIndices;
|
|
unsigned int k1, k2;
|
|
for (int i = 0; i < stackCount; ++i)
|
|
{
|
|
k1 = i * (sectorCount + 1); // beginning of current stack
|
|
k2 = k1 + sectorCount + 1; // beginning of next stack
|
|
|
|
for (int j = 0; j < sectorCount; ++j, ++k1, ++k2)
|
|
{
|
|
// 2 triangles per sector excluding 1st and last stacks
|
|
if (i != 0)
|
|
{
|
|
finalIndices.push_back(k1);
|
|
finalIndices.push_back(k2);
|
|
finalIndices.push_back(k1 + 1);
|
|
}
|
|
|
|
if (i != (stackCount - 1))
|
|
{
|
|
finalIndices.push_back(k1 + 1);
|
|
finalIndices.push_back(k2);
|
|
finalIndices.push_back(k2 + 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
Ref<Mesh> sphereMesh = CreateRef<Mesh>();
|
|
sphereMesh->SetMaterial(CreateRef<Material>());
|
|
sphereMesh->AddSurface(std::move(finalVertices), std::move(finalIndices));
|
|
return sphereMesh;
|
|
}
|
|
|
|
void Renderer::BeginDraw(Ref<Camera> camera)
|
|
{
|
|
Shader* lineShader = ShaderManager::GetShader("Resources/Shaders/line.shader");
|
|
lineShader->Bind();
|
|
lineShader->SetUniform("u_Projection", camera->GetPerspective());
|
|
lineShader->SetUniform("u_View", camera->GetTransform());
|
|
|
|
m_Shader->Bind();
|
|
m_Shader->SetUniform("u_Projection", camera->GetPerspective());
|
|
m_Shader->SetUniform("u_View", camera->GetTransform());
|
|
m_Shader->SetUniform("u_EyePosition", camera->GetTranslation().x, camera->GetTranslation().y, camera->GetTranslation().z);
|
|
}
|
|
|
|
int spotShadowMapCount = 0;
|
|
void Renderer::EndDraw()
|
|
{
|
|
ZoneScoped;
|
|
|
|
Shader* deferredShader = ShaderManager::GetShader("Resources/Shaders/deferred.shader");
|
|
deferredShader->Bind();
|
|
deferredShader->SetUniform("LightCount", 0);
|
|
|
|
for (int i = 0; i < m_Lights.size(); i++)
|
|
{
|
|
const std::string uniformAccessor = "Lights[" + std::to_string(i) + "].";
|
|
deferredShader->SetUniform(uniformAccessor + "Position", 0, 0, 0);
|
|
deferredShader->SetUniform(uniformAccessor + "Color", 0, 0, 0);
|
|
deferredShader->SetUniform(uniformAccessor + "Type", -1);
|
|
deferredShader->SetUniform(uniformAccessor + "CastShadow", 0);
|
|
deferredShader->SetUniform(uniformAccessor + "ShadowMapID", -1);
|
|
}
|
|
|
|
for (int i = 0; i < 8; i++)
|
|
{
|
|
deferredShader->SetUniform("SpotShadowMaps[" + std::to_string(i) + "]", 0);
|
|
}
|
|
|
|
m_Lights.clear();
|
|
spotShadowMapCount = 0;
|
|
}
|
|
|
|
// List of all lights queued to be used for rendering this frame.
|
|
std::vector<Light> Renderer::m_Lights;
|
|
|
|
void Renderer::RegisterDeferredLight(TransformComponent transform, LightComponent light)
|
|
{
|
|
Shader* deferredShader = ShaderManager::GetShader("Resources/Shaders/deferred.shader");
|
|
deferredShader->Bind();
|
|
|
|
Vector3 direction = light.GetDirection();
|
|
Vector3 pos = transform.GetGlobalTransform()[3];
|
|
Quat lightRotation = transform.GetGlobalRotation();
|
|
|
|
const int MaxSpotShadowMap = 8;
|
|
if (light.Type == Directional)
|
|
{
|
|
int shadowmapAmount = 0;
|
|
|
|
deferredShader->SetUniform("u_DirectionalLight.Shadow", light.CastShadows);
|
|
|
|
if (light.CastShadows)
|
|
{
|
|
for (int i = 0; i < CSM_AMOUNT; i++)
|
|
{
|
|
light.m_Framebuffers[i]->GetTexture(GL_DEPTH_ATTACHMENT)->Bind(17 + i);
|
|
const int shadowMapId = shadowmapAmount + i;
|
|
deferredShader->SetUniform("ShadowMaps[" + std::to_string(shadowMapId) + "]", 17 + i);
|
|
deferredShader->SetUniform("u_DirectionalLight.CascadeDepth[" + std::to_string(i) + "]", light.mCascadeSplitDepth[i]);
|
|
deferredShader->SetUniform("u_DirectionalLight.LightTransforms[" + std::to_string(i) + "]", light.mViewProjections[i]);
|
|
}
|
|
}
|
|
|
|
deferredShader->SetUniform("u_DirectionalLight.Direction", direction.x, direction.y, direction.z);
|
|
deferredShader->SetUniform("u_DirectionalLight.Color", light.Color.r * light.Strength, light.Color.g * light.Strength, light.Color.b * light.Strength);
|
|
|
|
shadowmapAmount += CSM_AMOUNT;
|
|
}
|
|
else
|
|
{
|
|
if (m_Lights.size() == MAX_LIGHT)
|
|
{
|
|
return;
|
|
}
|
|
|
|
m_Lights.push_back({ transform , light });
|
|
size_t idx = m_Lights.size();
|
|
|
|
const std::string uniformAccessor = "Lights[" + std::to_string(idx - 1) + "].";
|
|
deferredShader->SetUniform(uniformAccessor + "Position", pos.x, pos.y, pos.z);
|
|
deferredShader->SetUniform(uniformAccessor + "Color", light.Color.r * light.Strength, light.Color.g * light.Strength, light.Color.b * light.Strength);
|
|
deferredShader->SetUniform(uniformAccessor + "Type", static_cast<int>(light.Type));
|
|
deferredShader->SetUniform(uniformAccessor + "CastShadow", static_cast<int>(light.CastShadows));
|
|
|
|
if (light.Type == Spot)
|
|
{
|
|
direction = transform.GetGlobalRotation() * Vector3(0, 0, -1);
|
|
deferredShader->SetUniform(uniformAccessor + "Direction", direction.x, direction.y, direction.z);
|
|
deferredShader->SetUniform(uniformAccessor + "OuterAngle", glm::cos(Rad(light.OuterCutoff)));
|
|
deferredShader->SetUniform(uniformAccessor + "InnerAngle", glm::cos(Rad(light.Cutoff)));
|
|
|
|
if (light.CastShadows && spotShadowMapCount < MaxSpotShadowMap)
|
|
{
|
|
int shadowMapTextureSlot = 21 + spotShadowMapCount;
|
|
deferredShader->SetUniform(uniformAccessor + "ShadowMapID", spotShadowMapCount);
|
|
deferredShader->SetUniform(uniformAccessor + "Transform", light.GetProjection() * glm::inverse(transform.GetGlobalTransform()));
|
|
|
|
light.m_Framebuffers[0]->GetTexture(GL_DEPTH_ATTACHMENT)->Bind(shadowMapTextureSlot);
|
|
deferredShader->SetUniform("SpotShadowMaps[" + std::to_string(spotShadowMapCount) + "]", shadowMapTextureSlot);
|
|
spotShadowMapCount++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
deferredShader->SetUniform(uniformAccessor + "Direction", 0, 0, 0);
|
|
deferredShader->SetUniform(uniformAccessor + "OuterAngle", glm::cos(Rad(light.OuterCutoff)));
|
|
deferredShader->SetUniform(uniformAccessor + "InnerAngle", glm::cos(Rad(light.Cutoff)));
|
|
deferredShader->SetUniform(uniformAccessor + "ShadowMapID", -1);
|
|
}
|
|
|
|
deferredShader->SetUniform("LightCount", static_cast<int>(idx));
|
|
}
|
|
|
|
m_LightsUniformBuffer->Bind();
|
|
}
|
|
|
|
void Renderer::DrawLine(Vector3 start, Vector3 end, Color color, Matrix4 transform)
|
|
{
|
|
Shader* shader = ShaderManager::GetShader("Resources/Shaders/line.shader");
|
|
shader->Bind();
|
|
shader->SetUniform("u_Model", transform);
|
|
shader->SetUniform("u_Color", color.r, color.g, color.b, color.a);
|
|
|
|
std::vector<Vertex> vertices
|
|
{
|
|
{start, Vector2(0, 0), Vector3(-1, 0, 0)},
|
|
{end, Vector2(1, 0), Vector3(-1, -1, 0)}
|
|
};
|
|
|
|
VertexArray lineVertexArray = VertexArray();
|
|
lineVertexArray.Bind();
|
|
VertexBuffer lineVertexBuffer = VertexBuffer(&vertices, static_cast<int>(size(vertices)));
|
|
|
|
VertexBufferLayout vblayout = VertexBufferLayout();
|
|
vblayout.Push<float>(3);
|
|
lineVertexArray.AddBuffer(lineVertexBuffer, vblayout);
|
|
|
|
RenderCommand::DrawLines(0, 2);
|
|
}
|
|
|
|
void Renderer::DrawLine(Vector3 start, Vector3 end, Vector3 color)
|
|
{
|
|
|
|
//m_DebugShader->Bind();
|
|
//m_DebugShader->SetUniform("u_Color", color.r, color.g, color.b, color.a);
|
|
}
|
|
|
|
void Renderer::DrawCube(Matrix4 transform)
|
|
{
|
|
ZoneScoped;
|
|
CubeMesh->Bind();
|
|
RenderCommand::DrawArrays(0, 36);
|
|
}
|
|
|
|
|
|
void Renderer::DrawSphere(TransformComponent transform, glm::vec4 color)
|
|
{
|
|
|
|
}
|
|
|
|
void Renderer::DrawQuad(Matrix4 transform)
|
|
{
|
|
ZoneScoped;
|
|
|
|
QuadMesh->Bind();
|
|
RenderCommand::DrawArrays(0, 6);
|
|
}
|
|
}
|