#include "Renderer.h" #include #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 #include "Buffers/VertexBufferLayout.h" #include "src/Rendering/Textures/MaterialManager.h" #include "src/Rendering/Vertex.h" #include #include #include namespace Nuake { uint32_t Renderer::MAX_LIGHT = 42; unsigned int depthTexture; unsigned int depthFBO; Ref Renderer::CubeMesh; Ref Renderer::QuadMesh; Ref 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 Renderer::m_LightsUniformBuffer; RenderList Renderer::m_RenderList = RenderList(); std::vector CubeVertices { { Vector3(-1.0f, 1.0f, -1.0f), 0.0f, Vector3(-1, 0, 0), 0.0f }, { Vector3(-1.0f, -1.0f, -1.0f), 1.0f, Vector3(-1,-1, 0), 0.0f }, { Vector3(1.0f, -1.0f, -1.0f), 0.0f, Vector3(-1, 0, 0), 1.0f }, { Vector3(1.0f, -1.0f, -1.0f), 1.0f, Vector3(-1, 0, 0), 1.0f }, { Vector3(1.0f, 1.0f, -1.0f), 0.0f, Vector3(-1, 0, 0), 1.0f }, { Vector3(-1.0f, 1.0f, -1.0f), 1.0f, Vector3(-1, 0, 0), 0.0f }, { Vector3(-1.0f, -1.0f, 1.0f), 1.0f, Vector3(-1, 0, 0), 1.0f }, { Vector3(-1.0f, -1.0f, -1.0f), 1.0f, Vector3(-1, 0, 0), 1.0f }, { Vector3(-1.0f, 1.0f, -1.0f), 0.0f, Vector3(-1, 0, 0), 0.0f }, { Vector3(-1.0f, 1.0f, -1.0f), 1.0f, Vector3(-1,-1, 0), 0.0f }, { Vector3(-1.0f, 1.0f, 1.0f), 0.0f, Vector3(-1, 0, 0), 1.0f }, { Vector3(-1.0f, -1.0f, 1.0f), 1.0f, Vector3(-1, 0, 0), 1.0f }, { Vector3(1.0f, -1.0f, -1.0f), 0.0f, Vector3(-1, 0, 0), 1.0f }, { Vector3(1.0f, -1.0f, 1.0f), 1.0f, Vector3(-1, 0, 0), 0.0f }, { Vector3(1.0f, 1.0f, 1.0f), 1.0f, Vector3(-1, 0, 0), 1.0f }, { Vector3(1.0f, 1.0f, 1.0f), 1.0f, Vector3(-1, 0, 0), 1.0f }, { Vector3(1.0f, 1.0f, -1.0f), 0.0f, Vector3(-1, 0, 0), 0.0f }, { Vector3(1.0f, -1.0f, -1.0f), 1.0f, Vector3(-1,-1, 0), 0.0f }, { Vector3(-1.0f, -1.0f, 1.0f), 0.0f, Vector3(-1, 0, 0), 1.0f }, { Vector3(-1.0f, 1.0f, 1.0f), 1.0f, Vector3(-1, 0, 0), 1.0f }, { Vector3(1.0f, 1.0f, 1.0f), 0.0f, Vector3(-1, 0, 0), 1.0f }, { Vector3(1.0f, 1.0f, 1.0f), 1.0f, Vector3(-1, 0, 0), 0.0f }, { Vector3(1.0f, -1.0f, 1.0f), 1.0f, Vector3(-1, 0, 0), 1.0f }, { Vector3(-1.0f, -1.0f, 1.0f), 1.0f, Vector3(-1, 0, 0), 1.0f }, { Vector3(-1.0f, 1.0f, -1.0f), 0.0f, Vector3(-1, 0, 0), 0.0f }, { Vector3(1.0f, 1.0f, -1.0f), 1.0f, Vector3(-1,-1, 0), 0.0f }, { Vector3(1.0f, 1.0f, 1.0f), 0.0f, Vector3(-1, 0, 0), 1.0f }, { Vector3(1.0f, 1.0f, 1.0f), 1.0f, Vector3(-1, 0, 0), 1.0f }, { Vector3(-1.0f, 1.0f, 1.0f), 0.0f, Vector3(-1, 0, 0), 1.0f }, { Vector3(-1.0f, 1.0f, -1.0f), 1.0f, Vector3(-1, 0, 0), 0.0f }, { Vector3(-1.0f, -1.0f, -1.0f), 1.0f, Vector3(-1, 0, 0), 1.0f }, { Vector3(-1.0f, -1.0f, 1.0f), 1.0f, Vector3(-1, 0, 0), 1.0f }, { Vector3(1.0f, -1.0f, -1.0f), 0.0f, Vector3(-1, 0, 0), 0.0f }, { Vector3(1.0f, -1.0f, -1.0f), 1.0f, Vector3(-1,-1, 0), 0.0f }, { Vector3(-1.0f, -1.0f, 1.0f), 0.0f, Vector3(-1, 0, 0), 1.0f }, { Vector3(1.0f, -1.0f, 1.0f), 1.0f, Vector3(-1, 0, 0), 1.0f } }; std::vector CubeIndices; std::vector QuadVertices { { Vector3(-1.0f, 1.0f, 0.0f), 0.0f, Vector3(0, 0, 1), 1.0f, Vector4(1, 0, 0, 0), Vector4(0, 1, 0, 0) }, { Vector3(1.0f, 1.0f, 0.0f), 1.0f, Vector3(0, 0, 1), 1.0f, Vector4(1, 0, 0, 0), Vector4(0, 1, 0, 0) }, { Vector3(-1.0f, -1.0f, 0.0f), 0.0f, Vector3(0, 0, 1), 0.0f, Vector4(1, 0, 0, 0), Vector4(0, 1, 0, 0) }, { Vector3(1.0f, -1.0f, 0.0f), 1.0f, Vector3(0, 0, 1), 0.0f, Vector4(1, 0, 0, 0), Vector4(0, 1, 0, 0) }, { Vector3(-1.0f, -1.0f, 0.0f), 0.0f, Vector3(0, 0, 1), 0.0f, Vector4(1, 0, 0, 0), Vector4(0, 1, 0, 0) }, { Vector3(1.0f, 1.0f, 0.0f), 1.0f, Vector3(0, 0, 1), 1.0f, Vector4(1, 0, 0, 0), Vector4(0, 1, 0, 0) } }; void Renderer::Init() { RenderCommand::SetRendererAPI(RendererPlatforms::Vulkan); //ShaderManager::LoadShaders(); //m_LightsUniformBuffer = CreateRef(128); // //Ref defaultMaterial = CreateRef(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(); //CubeMesh->AddSurface(CubeVertices, CubeIndices); //CubeMesh->SetMaterial(defaultMaterial); // //QuadMesh = CreateRef(); //QuadMesh->AddSurface(QuadVertices, { 0, 1, 2, 3, 4, 5 }); //QuadMesh->SetMaterial(defaultMaterial); // //SphereMesh = CreateSphereMesh(); } void Renderer::LoadShaders() { } void Renderer::SubmitMesh(Ref 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 Renderer::CreateSphereMesh() { const float sectorCount = 36; const float stackCount = 36; const float radius = 0.5f; const float PI = acos(-1.0f); // new std::vector 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_x = t; newVertex.uv_y = s; finalVertices.push_back(newVertex); } } std::vector 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 sphereMesh = CreateRef(); sphereMesh->SetMaterial(CreateRef()); sphereMesh->AddSurface(std::move(finalVertices), std::move(finalIndices)); return sphereMesh; } void Renderer::BeginDraw(Ref 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 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(light.Type)); deferredShader->SetUniform(uniformAccessor + "CastShadow", static_cast(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(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 vertices { {start, 0.0f, Vector3(-1, 0, 0), 1.0f}, {end, 1.0f, Vector3(-1, -1, 0), 0.0f} }; VertexArray lineVertexArray = VertexArray(); lineVertexArray.Bind(); VertexBuffer lineVertexBuffer = VertexBuffer(&vertices, static_cast(size(vertices))); VertexBufferLayout vblayout = VertexBufferLayout(); vblayout.Push(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); } }