This commit is contained in:
Kbz-8
2025-06-16 15:18:27 +02:00
parent 15510fa8a7
commit cd7e5ad26f
165 changed files with 78107 additions and 0 deletions

39
Runtime/Sources/Graphics/Actor.cpp git.filemode.normal_file
View File

@@ -0,0 +1,39 @@
#include <Graphics/Actor.h>
#include <Platform/Inputs.h>
namespace Scop
{
Actor::Actor()
{
m_uuid = UUID();
if(p_script)
p_script->OnInit(this);
}
Actor::Actor(Model model) : m_model(std::move(model))
{
m_uuid = UUID();
if(p_script)
p_script->OnInit(this);
}
Actor::Actor(std::uint64_t uuid, Model model) : m_model(std::move(model)), m_uuid(uuid)
{
if(p_script)
p_script->OnInit(this);
}
void Actor::Update(NonOwningPtr<Scene> scene, Inputs& input, float delta)
{
if(p_script)
p_script->OnUpdate(scene, this, input, delta);
}
Actor::~Actor()
{
if(p_script)
p_script->OnQuit(this);
if(m_custom_pipeline.has_value() && m_custom_pipeline->data_uniform_buffer)
m_custom_pipeline->data_uniform_buffer->Destroy();
}
}

View File

@@ -0,0 +1,77 @@
#include <Graphics/Cameras/FirstPerson3D.h>
#include <Platform/Inputs.h>
namespace Scop
{
FirstPerson3D::FirstPerson3D() : BaseCamera(), c_up(0, 1, 0), m_position(0.0, 0.0, 0.0)
{}
FirstPerson3D::FirstPerson3D(Vec3f position, float fov, float speed) : BaseCamera(), m_position(std::move(position)), c_up(0, 1, 0), c_speed(speed), m_fov(fov)
{}
void FirstPerson3D::Update(class Inputs& input, float aspect, float timestep)
{
UpdateView();
m_target = m_position + m_direction;
m_view = Mat4f::LookAt(m_position, m_target, c_up);
m_proj = Mat4f::Perspective(RadianAnglef(m_fov), aspect, 0.1f, 100'000.f);
if(m_inputs_blocked)
return;
if(input.IsMouseGrabbed())
{
m_theta -= input.GetXRel() * c_sensivity;
m_phi -= input.GetYRel() * c_sensivity;
}
if(input.IsKeyPressed(SDL_SCANCODE_ESCAPE))
input.ReleaseMouse();
else if(input.IsMouseButtonPressed(SDL_BUTTON_LEFT))
input.GrabMouse();
m_mov = Vec3f(0.0);
if(input.IsKeyPressed(SDL_SCANCODE_W) || input.IsKeyPressed(SDL_SCANCODE_UP))
m_mov -= m_forward;
if(input.IsKeyPressed(SDL_SCANCODE_S) || input.IsKeyPressed(SDL_SCANCODE_DOWN))
m_mov += m_forward;
if(input.IsKeyPressed(SDL_SCANCODE_D) || input.IsKeyPressed(SDL_SCANCODE_RIGHT))
m_mov -= m_left;
if(input.IsKeyPressed(SDL_SCANCODE_A) || input.IsKeyPressed(SDL_SCANCODE_LEFT))
m_mov += m_left;
if(input.IsKeyPressed(SDL_SCANCODE_LSHIFT) || input.IsKeyPressed(SDL_SCANCODE_RSHIFT))
m_mov -= c_up;
if(input.IsKeyPressed(SDL_SCANCODE_SPACE))
m_mov += c_up;
/*
if(input.IsMouseWheelUp())
m_speed_factor *= 1.5f;
if(input.IsMouseWheelDown())
m_speed_factor /= 1.5f;
*/
if(input.IsKeyPressed(SDL_SCANCODE_Q))
m_speed_factor = 20.0f;
else
m_speed_factor = 1.0f;
m_position += m_mov * c_speed * m_speed_factor * timestep;
}
void FirstPerson3D::UpdateView()
{
m_phi = m_phi > 89 ? 89 : m_phi;
m_phi = m_phi < -89 ? -89 : m_phi;
// Spherical coordinate system
m_direction.x = std::cos(m_phi * Pi<float>() / 180) * std::cos(m_theta * Pi<float>() / 180);
m_direction.y = std::sin(m_phi * Pi<float>() / 180);
m_direction.z = std::cos(m_phi * Pi<float>() / 180) * std::sin(-m_theta * Pi<float>() / 180);
m_left = c_up.CrossProduct(m_direction);
m_left.Normalize();
m_forward = c_up.CrossProduct(m_left);
m_forward.Normalize();
}
}

65
Runtime/Sources/Graphics/Font.cpp git.filemode.normal_file
View File

@@ -0,0 +1,65 @@
#include <Graphics/Font.h>
#include <Core/Logs.h>
#include <fstream>
#define STBRP_ASSERT(x) Scop::Assert(x, "internal stb assertion " #x)
#define STB_RECT_PACK_IMPLEMENTATION
#include <stb_rect_pack.h>
#define STB_TRUETYPE_IMPLEMENTATION
#include <stb_truetype.h>
namespace Scop
{
void Font::BuildFont()
{
std::vector<std::uint8_t> file_bytes;
if(std::holds_alternative<std::filesystem::path>(m_build_data))
{
std::ifstream file(std::get<std::filesystem::path>(m_build_data), std::ios::binary);
if(!file.is_open())
{
Error("Font: cannot open font file, %", m_name);
return;
}
std::ifstream::pos_type file_size = std::filesystem::file_size(std::get<std::filesystem::path>(m_build_data));
file.seekg(0, std::ios::beg);
file_bytes.resize(file_size);
file.read(reinterpret_cast<char*>(file_bytes.data()), file_size);
file.close();
}
CPUBuffer bitmap(RANGE * RANGE);
stbtt_pack_context pc;
stbtt_PackBegin(&pc, bitmap.GetData(), RANGE, RANGE, RANGE, 1, nullptr);
if(std::holds_alternative<std::filesystem::path>(m_build_data))
stbtt_PackFontRange(&pc, file_bytes.data(), 0, m_scale, 32, 96, m_cdata.data());
else
stbtt_PackFontRange(&pc, std::get<std::vector<std::uint8_t>>(m_build_data).data(), 0, m_scale, 32, 96, m_cdata.data());
stbtt_PackEnd(&pc);
// TODO : find better solution; No, using VK_FORMAT_R8_SRGB does not work
CPUBuffer vulkan_bitmap(RANGE * RANGE * 4);
for(int i = 0, j = 0; i < RANGE * RANGE; i++, j += 4)
{
vulkan_bitmap.GetData()[j + 0] = bitmap.GetData()[i];
vulkan_bitmap.GetData()[j + 1] = bitmap.GetData()[i];
vulkan_bitmap.GetData()[j + 2] = bitmap.GetData()[i];
vulkan_bitmap.GetData()[j + 3] = bitmap.GetData()[i];
}
m_atlas.Init(std::move(vulkan_bitmap), RANGE, RANGE, VK_FORMAT_R8G8B8A8_SRGB, false, m_name + "_font_atlas_" + std::to_string(m_scale));
Message("Font: loaded % with a scale of %", m_name, m_scale);
}
void Font::Destroy()
{
if(!m_atlas.IsInit())
return;
m_atlas.Destroy();
Message("Font: unloaded % with a scale of %", m_name, m_scale);
}
}

45
Runtime/Sources/Graphics/Loaders/BMP.cpp git.filemode.normal_file
View File

@@ -0,0 +1,45 @@
#include <Graphics/Loaders/BMP.h>
#include <Maths/Vec3.h>
#include <fstream>
namespace Scop
{
CPUBuffer LoadBMPFile(const std::filesystem::path& path, Vec2ui32& dimensions)
{
if(path.extension() != ".bmp")
{
Error("BMP loader: not a BMP file, %", path);
return {};
}
std::ifstream file(path, std::ios::binary);
if(!file.is_open())
{
Error("BMP loader: could not open %", path);
return {};
}
std::int16_t bpp;
file.seekg(18, std::ios_base::beg);
file.read(reinterpret_cast<char*>(&dimensions.x), sizeof(dimensions.x));
file.read(reinterpret_cast<char*>(&dimensions.y), sizeof(dimensions.y));
file.seekg(28, std::ios_base::beg);
file.read(reinterpret_cast<char*>(&bpp), sizeof(bpp));
file.seekg(54, std::ios_base::beg);
if(bpp != 24)
Warning("BMP loader: warning while loading %, cannot handle yet different color palette sizes", path);
CPUBuffer buffer{ dimensions.x * dimensions.y * 4 };
for(std::size_t i = 0; i < buffer.GetSize(); i += 4)
{
Vec3b data{ 0, 0, 0 };
data.x = (file.eof() ? 0x00 : file.get());
data.y = (file.eof() ? 0x00 : file.get());
data.z = (file.eof() ? 0x00 : file.get());
buffer.GetData()[i + 0] = data.z;
buffer.GetData()[i + 1] = data.y;
buffer.GetData()[i + 2] = data.x;
buffer.GetData()[i + 3] = 0xFF;
}
Message("BMP Loader: loaded %", path);
return buffer;
}
}

171
Runtime/Sources/Graphics/Loaders/OBJ.cpp git.filemode.normal_file
View File

@@ -0,0 +1,171 @@
#include <Graphics/Loaders/OBJ.h>
#include <Core/Logs.h>
#include <set>
#include <fstream>
#include <algorithm>
namespace Scop
{
std::optional<ObjData> LoadObjFromFile(const std::filesystem::path& path)
{
if(!std::filesystem::exists(path))
{
Error("OBJ loader: OBJ file does not exists; %", path);
return std::nullopt;
}
char line[1024];
std::string op;
std::istringstream line_in;
std::set<std::string> groups;
groups.insert("default");
std::ifstream in(path);
ObjData data;
while(in.good())
{
in.getline(line, 1023);
line_in.clear();
line_in.str(line);
if(!(line_in >> op))
continue;
if(op == "v")
{
Vec3f v;
line_in >> v.x;
line_in >> v.y;
line_in >> v.z;
data.vertex.push_back(std::move(v));
}
else if(op == "vt")
{
Vec2f v;
line_in >> v.x;
line_in >> v.y;
data.tex_coord.push_back(std::move(v));
}
else if(op == "vn")
{
Vec3f v;
line_in >> v.x;
line_in >> v.y;
line_in >> v.z;
data.normal.push_back(std::move(v));
}
else if(op == "vc")
{
Vec4f v;
line_in >> v.x;
line_in >> v.y;
line_in >> v.z;
line_in >> v.w;
data.color.push_back(std::move(v));
}
else if(op == "g")
{
groups.clear();
while(line_in >> groups);
groups.insert("default");
}
else if(op == "f")
{
std::vector<ObjData::FaceVertex> list;
while(line_in >> list);
for(const auto& group : groups)
{
ObjData::FaceList& fl = data.faces[group];
fl.second.push_back(fl.first.size());
fl.first.insert(fl.first.end(), list.begin(), list.end());
}
}
}
for(auto& [_, face] : data.faces)
{
ObjData::FaceList& fl = face;
fl.second.push_back(fl.first.size());
}
Message("OBJ Loader: loaded %", path);
return data;
}
static void TesselateObjData(std::vector<ObjData::FaceVertex>& input, std::vector<std::uint32_t>& input_start) noexcept
{
std::vector<ObjData::FaceVertex> output;
std::vector<std::uint32_t> output_start;
output.reserve(input.size());
output_start.reserve(input_start.size());
for(auto s = input_start.begin(); s != input_start.end() - 1; ++s)
{
const std::uint32_t size = *(s + 1) - *s;
if(size > 3)
{
const ObjData::FaceVertex & start_vertex = input[*s];
for(std::size_t i = 1; i < size - 1; i++)
{
output_start.push_back(output.size());
output.push_back(start_vertex);
output.push_back(input[*s + i]);
output.push_back(input[*s + i + 1]);
}
}
else
{
output_start.push_back(output.size());
output.insert(output.end(), input.begin() + *s, input.begin() + *(s + 1));
}
}
output_start.push_back(output.size());
input.swap(output);
input_start.swap(output_start);
}
void TesselateObjData(ObjData& obj)
{
for(auto& face : obj.faces)
{
ObjData::FaceList& fl = face.second;
TesselateObjData(fl.first, fl.second);
}
Message("OBJ Loader : object data tesselated");
}
ObjModel ConvertObjDataToObjModel(const ObjData& data)
{
std::vector<ObjData::FaceVertex> unique(data.faces.find("default")->second.first);
std::sort(unique.begin(), unique.end());
//unique.erase(std::unique(unique.begin(), unique.end()), unique.end());
ObjModel model;
for(auto& face : unique)
{
model.vertex.push_back(data.vertex[face.v]);
if(!data.tex_coord.empty())
{
const int index = (face.t > -1) ? face.t : face.v;
model.tex_coord.push_back(data.tex_coord[index]);
}
if(!data.normal.empty())
{
const int index = (face.n > -1) ? face.n : face.v;
model.normal.push_back(data.normal[index]);
}
if(!data.color.empty())
{
const int index = face.v;
model.color.push_back(data.color[index]);
}
}
for(auto& [group, faces] : data.faces)
{
std::vector<std::uint32_t>& v = model.faces[group];
v.reserve(faces.first.size());
for(auto& face : faces.first)
v.push_back(std::distance(unique.begin(), std::lower_bound(unique.begin(), unique.end(), face)));
}
return model;
}
}

28
Runtime/Sources/Graphics/Mesh.cpp git.filemode.normal_file
View File

@@ -0,0 +1,28 @@
#include <Graphics/Mesh.h>
#include <Utils/Buffer.h>
#include <cstring>
namespace Scop
{
void Mesh::Draw(VkCommandBuffer cmd, std::size_t& drawcalls, std::size_t& polygondrawn) const noexcept
{
for(std::size_t i = 0; i < m_sub_meshes.size(); i++)
Draw(cmd, drawcalls, polygondrawn, i);
}
void Mesh::Draw(VkCommandBuffer cmd, std::size_t& drawcalls, std::size_t& polygondrawn, std::size_t submesh_index) const noexcept
{
Verify(submesh_index < m_sub_meshes.size(), "invalid submesh index");
m_sub_meshes[submesh_index].buffer.BindVertex(cmd);
m_sub_meshes[submesh_index].buffer.BindIndex(cmd);
RenderCore::Get().vkCmdDrawIndexed(cmd, m_sub_meshes[submesh_index].index_size, 1, 0, 0, 0);
polygondrawn += m_sub_meshes[submesh_index].triangle_count;
drawcalls++;
}
Mesh::~Mesh()
{
for(auto& mesh : m_sub_meshes)
mesh.buffer.Destroy();
}
}

565
Runtime/Sources/Graphics/MeshFactory.cpp git.filemode.normal_file
View File

@@ -0,0 +1,565 @@
#include <Graphics/MeshFactory.h>
#include <Graphics/Mesh.h>
#include <Renderer/Vertex.h>
#include <Maths/Constants.h>
#include <Maths/Quaternions.h>
#include <cmath>
#include <vector>
namespace Scop
{
std::shared_ptr<Mesh> CreateQuad(float x, float y, float width, float height)
{
std::vector<Vertex> data(4);
data[0].position = Vec4f(x, y, 0.0f, 1.0f);
data[0].uv = Vec2f(1.0f, 1.0f);
data[1].position = Vec4f(x + width, y, 0.0f, 1.0f);
data[1].uv = Vec2f(0.0f, 1.0f);
data[2].position = Vec4f(x + width, y + height, 0.0f, 1.0f);
data[2].uv = Vec2f(0.0f, 0.0f);
data[3].position = Vec4f(x, y + height, 0.0f, 1.0f);
data[3].uv = Vec2f(1.0f, 0.0f);
std::vector<std::uint32_t> indices = {
0,
1,
2,
2,
3,
0,
};
std::shared_ptr<Mesh> mesh = std::make_shared<Mesh>();
mesh->AddSubMesh({ std::move(data), std::move(indices) });
return mesh;
}
std::shared_ptr<Mesh> CreateQuad(const Vec2f& position, const Vec2f& size)
{
return CreateQuad(position.x, position.y, size.x, size.y);
}
std::shared_ptr<Mesh> CreateQuad()
{
std::vector<Vertex> data(4);
data[0].position = Vec4f(-1.0f, -1.0f, 0.0f, 1.0f);
data[0].uv = Vec2f(0.0f, 0.0f);
data[0].color = Vec4f(1.0f);
data[1].position = Vec4f(1.0f, -1.0f, 0.0f, 1.0f);
data[1].color = Vec4f(1.0f);
data[1].uv = Vec2f(1.0f, 0.0f);
data[2].position = Vec4f(1.0f, 1.0f, 0.0f, 1.0f);
data[2].color = Vec4f(1.0f);
data[2].uv = Vec2f(1.0f, 1.0f);
data[3].position = Vec4f(-1.0f, 1.0f, 0.0f, 1.0f);
data[3].color = Vec4f(1.0f);
data[3].uv = Vec2f(0.0f, 1.0f);
std::vector<std::uint32_t> indices = {
0,
1,
2,
2,
3,
0,
};
std::shared_ptr<Mesh> mesh = std::make_shared<Mesh>();
mesh->AddSubMesh({ std::move(data), std::move(indices) });
return mesh;
}
std::shared_ptr<Mesh> CreateCube()
{
// v6----- v5
// /| /|
// v1------v0|
// | | | |
// | |v7---|-|v4
// |/ |/
// v2------v3
std::vector<Vertex> data(24);
data[0].position = Vec4f(1.0f, 1.0f, 1.0f, 1.0f);
data[0].color = Vec4f(1.0f);
data[0].normal = Vec4f(0.0f, 0.0f, 1.0f, 1.0f);
data[1].position = Vec4f(-1.0f, 1.0f, 1.0f, 1.0f);
data[1].color = Vec4f(1.0f);
data[1].normal = Vec4f(0.0f, 0.0f, 1.0f, 1.0f);
data[2].position = Vec4f(-1.0f, -1.0f, 1.0f, 1.0f);
data[2].color = Vec4f(1.0f);
data[2].normal = Vec4f(0.0f, 0.0f, 1.0f, 1.0f);
data[3].position = Vec4f(1.0f, -1.0f, 1.0f, 1.0f);
data[3].color = Vec4f(1.0f);
data[3].normal = Vec4f(0.0f, 0.0f, 1.0f, 1.0f);
data[4].position = Vec4f(1.0f, 1.0f, 1.0f, 1.0f);
data[4].color = Vec4f(1.0f);
data[4].normal = Vec4f(1.0f, 0.0f, 0.0f, 1.0f);
data[5].position = Vec4f(1.0f, -1.0f, 1.0f, 1.0f);
data[5].color = Vec4f(1.0f);
data[5].normal = Vec4f(1.0f, 0.0f, 0.0f, 1.0f);
data[6].position = Vec4f(1.0f, -1.0f, -1.0f, 1.0f);
data[6].color = Vec4f(1.0f);
data[6].normal = Vec4f(1.0f, 0.0f, 0.0f, 1.0f);
data[7].position = Vec4f(1.0f, 1.0f, -1.0f, 1.0f);
data[7].color = Vec4f(1.0f);
data[7].normal = Vec4f(1.0f, 0.0f, 0.0f, 1.0f);
data[8].position = Vec4f(1.0f, 1.0f, 1.0f, 1.0f);
data[8].color = Vec4f(1.0f);
data[8].normal = Vec4f(0.0f, 1.0f, 0.0f, 1.0f);
data[9].position = Vec4f(1.0f, 1.0f, -1.0f, 1.0f);
data[9].color = Vec4f(1.0f);
data[9].normal = Vec4f(0.0f, 1.0f, 0.0f, 1.0f);
data[10].position = Vec4f(-1.0f, 1.0f, -1.0f, 1.0f);
data[10].color = Vec4f(1.0f);
data[10].normal = Vec4f(0.0f, 1.0f, 0.0f, 1.0f);
data[11].position = Vec4f(-1.0f, 1.0f, 1.0f, 1.0f);
data[11].color = Vec4f(1.0f);
data[11].normal = Vec4f(0.0f, 1.0f, 0.0f, 1.0f);
data[12].position = Vec4f(-1.0f, 1.0f, 1.0f, 1.0f);
data[12].color = Vec4f(1.0f);
data[12].normal = Vec4f(-1.0f, 0.0f, 0.0f, 1.0f);
data[13].position = Vec4f(-1.0f, 1.0f, -1.0f, 1.0f);
data[13].color = Vec4f(1.0f);
data[13].normal = Vec4f(-1.0f, 0.0f, 0.0f, 1.0f);
data[14].position = Vec4f(-1.0f, -1.0f, -1.0f, 1.0f);
data[14].color = Vec4f(1.0f);
data[14].normal = Vec4f(-1.0f, 0.0f, 0.0f, 1.0f);
data[15].position = Vec4f(-1.0f, -1.0f, 1.0f, 1.0f);
data[15].color = Vec4f(1.0f);
data[15].normal = Vec4f(-1.0f, 0.0f, 0.0f, 1.0f);
data[16].position = Vec4f(-1.0f, -1.0f, -1.0f, 1.0f);
data[16].color = Vec4f(1.0f);
data[16].normal = Vec4f(0.0f, -1.0f, 0.0f, 1.0f);
data[17].position = Vec4f(1.0f, -1.0f, -1.0f, 1.0f);
data[17].color = Vec4f(1.0f);
data[17].normal = Vec4f(0.0f, -1.0f, 0.0f, 1.0f);
data[18].position = Vec4f(1.0f, -1.0f, 1.0f, 1.0f);
data[18].color = Vec4f(1.0f);
data[18].normal = Vec4f(0.0f, -1.0f, 0.0f, 1.0f);
data[19].position = Vec4f(-1.0f, -1.0f, 1.0f, 1.0f);
data[19].color = Vec4f(1.0f);
data[19].normal = Vec4f(0.0f, -1.0f, 0.0f, 1.0f);
data[20].position = Vec4f(1.0f, -1.0f, -1.0f, 1.0f);
data[20].color = Vec4f(1.0f);
data[20].normal = Vec4f(0.0f, 0.0f, -1.0f, 1.0f);
data[21].position = Vec4f(-1.0f, -1.0f, -1.0f, 1.0f);
data[21].color = Vec4f(1.0f);
data[21].normal = Vec4f(0.0f, 0.0f, -1.0f, 1.0f);
data[22].position = Vec4f(-1.0f, 1.0f, -1.0f, 1.0f);
data[22].color = Vec4f(1.0f);
data[22].normal = Vec4f(0.0f, 0.0f, -1.0f, 1.0f);
data[23].position = Vec4f(1.0f, 1.0f, -1.0f, 1.0f);
data[23].color = Vec4f(1.0f);
data[23].normal = Vec4f(0.0f, 0.0f, -1.0f, 1.0f);
for(int i = 0; i < 6; i++)
{
data[i * 4 + 0].uv = Vec2f(0.0f, 0.0f);
data[i * 4 + 1].uv = Vec2f(1.0f, 0.0f);
data[i * 4 + 2].uv = Vec2f(1.0f, 1.0f);
data[i * 4 + 3].uv = Vec2f(0.0f, 1.0f);
}
std::vector<std::uint32_t> indices = {
0, 1, 2, 0, 2, 3, // Right
4, 5, 6, 4, 6, 7, // Front
8, 9, 10, 8, 10, 11, // Top
12, 13, 14, 12, 14, 15, // Back
16, 17, 18, 16, 18, 19, // Bottom
20, 21, 22, 20, 22, 23 // Left
};
std::shared_ptr<Mesh> mesh = std::make_shared<Mesh>();
mesh->AddSubMesh({ std::move(data), std::move(indices) });
return mesh;
}
std::shared_ptr<Mesh> CreatePyramid()
{
std::vector<Vertex> data(18);
data[0].position = Vec4f(1.0f, 1.0f, -1.0f, 1.0f);
data[0].color = Vec4f(1.0f);
data[0].uv = Vec2f(0.24f, 0.20f);
data[0].normal = Vec4f(0.0f, 0.8948f, 0.4464f, 1.0f);
data[1].position = Vec4f(-1.0f, 1.0f, -1.0f, 1.0f);
data[1].color = Vec4f(1.0f);
data[1].uv = Vec2f(0.24f, 0.81f);
data[1].normal = Vec4f(0.0f, 0.8948f, 0.4464f, 1.0f);
data[2].position = Vec4f(0.0f, 0.0f, 1.0f, 1.0f);
data[2].color = Vec4f(1.0f);
data[2].uv = Vec2f(0.95f, 0.50f);
data[2].normal = Vec4f(0.0f, 0.8948f, 0.4464f, 1.0f);
data[3].position = Vec4f(-1.0f, 1.0f, -1.0f, 1.0f);
data[3].color = Vec4f(1.0f);
data[3].uv = Vec2f(0.24f, 0.21f);
data[3].normal = Vec4f(-0.8948f, 0.0f, 0.4464f, 1.0f);
data[4].position = Vec4f(-1.0f, -1.0f, -1.0f, 1.0f);
data[4].color = Vec4f(1.0f);
data[4].uv = Vec2f(0.24f, 0.81f);
data[4].normal = Vec4f(-0.8948f, 0.0f, 0.4464f, 1.0f);
data[5].position = Vec4f(0.0f, 0.0f, 1.0f, 1.0f);
data[5].color = Vec4f(1.0f);
data[5].uv = Vec2f(0.95f, 0.50f);
data[5].normal = Vec4f(-0.8948f, 0.0f, 0.4464f, 1.0f);
data[6].position = Vec4f(1.0f, 1.0f, -1.0f, 1.0f);
data[6].color = Vec4f(1.0f);
data[6].uv = Vec2f(0.24f, 0.81f);
data[6].normal = Vec4f(0.8948f, 0.0f, 0.4475f, 1.0f);
data[7].position = Vec4f(0.0f, 0.0f, 1.0f, 1.0f);
data[7].color = Vec4f(1.0f);
data[7].uv = Vec2f(0.95f, 0.50f);
data[7].normal = Vec4f(0.8948f, 0.0f, 0.4475f, 1.0f);
data[8].position = Vec4f(1.0f, -1.0f, -1.0f, 1.0f);
data[8].color = Vec4f(1.0f);
data[8].uv = Vec2f(0.24f, 0.21f);
data[8].normal = Vec4f(0.8948f, 0.0f, 0.4475f, 1.0f);
data[9].position = Vec4f(-1.0f, -1.0f, -1.0f, 1.0f);
data[9].color = Vec4f(1.0f);
data[9].uv = Vec2f(0.24f, 0.21f);
data[9].normal = Vec4f(0.0f, -0.8948f, 0.448f, 1.0f);
data[10].position = Vec4f(1.0f, -1.0f, -1.0f, 1.0f);
data[10].color = Vec4f(1.0f);
data[10].uv = Vec2f(0.24f, 0.81f);
data[10].normal = Vec4f(0.0f, -0.8948f, 0.448f, 1.0f);
data[11].position = Vec4f(0.0f, 0.0f, 1.0f, 1.0f);
data[11].color = Vec4f(1.0f);
data[11].uv = Vec2f(0.95f, 0.50f);
data[11].normal = Vec4f(0.0f, -0.8948f, 0.448f, 1.0f);
data[12].position = Vec4f(-1.0f, 1.0f, -1.0f, 1.0f);
data[12].color = Vec4f(1.0f);
data[12].uv = Vec2f(0.0f, 0.0f);
data[12].normal = Vec4f(0.0f, 0.0f, -1.0f, 1.0f);
data[13].position = Vec4f(1.0f, 1.0f, -1.0f, 1.0f);
data[13].color = Vec4f(1.0f);
data[13].uv = Vec2f(0.0f, 1.0f);
data[13].normal = Vec4f(0.0f, 0.0f, -1.0f, 1.0f);
data[14].position = Vec4f(1.0f, -1.0f, -1.0f, 1.0f);
data[14].color = Vec4f(1.0f);
data[14].uv = Vec2f(1.0f, 1.0f);
data[14].normal = Vec4f(0.0f, 0.0f, -1.0f, 1.0f);
data[15].position = Vec4f(-1.0f, -1.0f, -1.0f, 1.0f);
data[15].color = Vec4f(1.0f);
data[15].uv = Vec2f(0.96f, 0.0f);
data[15].normal = Vec4f(0.0f, 0.0f, -1.0f, 1.0f);
data[16].position = Vec4f(0.0f, 0.0f, 0.0f, 1.0f);
data[16].color = Vec4f(1.0f);
data[16].uv = Vec2f(0.0f, 0.0f);
data[16].normal = Vec4f(0.0f, 0.0f, 0.0f, 1.0f);
data[17].position = Vec4f(0.0f, 0.0f, 0.0f, 1.0f);
data[17].color = Vec4f(1.0f);
data[17].uv = Vec2f(0.0f, 0.0f);
data[17].normal = Vec4f(0.0f, 0.0f, 0.0f, 1.0f);
std::vector<std::uint32_t> indices = {
0, 1, 2,
3, 4, 5,
6, 7, 8,
9, 10, 11,
12, 13, 14,
15, 12, 14
};
std::shared_ptr<Mesh> mesh = std::make_shared<Mesh>();
mesh->AddSubMesh({ std::move(data), std::move(indices) });
return mesh;
}
std::shared_ptr<Mesh> CreateSphere(std::uint32_t x_segments, std::uint32_t y_segments)
{
std::vector<Vertex> data;
float sector_count = static_cast<float>(x_segments);
float stack_count = static_cast<float>(y_segments);
float sector_step = 2 * Pi<float>() / sector_count;
float stack_step = Pi<float>() / stack_count;
float radius = 1.0f;
for(int i = 0; i <= stack_count; ++i)
{
float stack_angle = Pi<float>() / 2 - i * stack_step;
float xy = radius * std::cos(stack_angle);
float z = radius * std::sin(stack_angle);
for(int j = 0; j <= sector_count; ++j)
{
float sector_angle = j * sector_step;
float x = xy * cosf(sector_angle);
float y = xy * sinf(sector_angle);
float s = static_cast<float>(j / sector_count);
float t = static_cast<float>(i / stack_count);
Vertex vertex;
vertex.position = Vec4f(x, y, z, 1.0f);
vertex.uv = Vec2f(s, t);
vertex.normal = vertex.position.Normalize();
data.emplace_back(vertex);
}
}
std::vector<std::uint32_t> indices;
std::uint32_t k1, k2;
for(uint32_t i = 0; i < stack_count; ++i)
{
k1 = i * (static_cast<std::uint32_t>(sector_count) + 1U);
k2 = k1 + static_cast<std::uint32_t>(sector_count) + 1U;
for(std::uint32_t j = 0; j < sector_count; ++j, ++k1, ++k2)
{
if(i != 0)
{
indices.push_back(k1);
indices.push_back(k2);
indices.push_back(k1 + 1);
}
if(i != (stack_count - 1))
{
indices.push_back(k1 + 1);
indices.push_back(k2);
indices.push_back(k2 + 1);
}
}
}
std::shared_ptr<Mesh> mesh = std::make_shared<Mesh>();
mesh->AddSubMesh({ std::move(data), std::move(indices) });
return mesh;
}
std::shared_ptr<Mesh> CreatePlane(float width, float height, const Vec3f& normal)
{
Vec3 vec = normal * 90.0f;
std::vector<Vertex> data(4);
data[0].position = Vec4f(-width * 0.5f, -1.0f, -height * 0.5f);
data[0].normal = normal;
data[0].uv = Vec2f(0.0f, 0.0f);
data[1].position = Vec4f(-width * 0.5f, -1.0f, height * 0.5f);
data[1].normal = normal;
data[1].uv = Vec2f(0.0f, 1.0f);
data[2].position = Vec4f(width * 0.5f, 1.0f, height * 0.5f);
data[2].normal = normal;
data[2].uv = Vec2f(1.0f, 1.0f);
data[3].position = Vec4f(width * 0.5f, 1.0f, -height * 0.5f);
data[3].normal = normal;
data[3].uv = Vec2f(1.0f, 0.0f);
std::vector<std::uint32_t> indices = { 0, 1, 2, 2, 3, 0 };
std::shared_ptr<Mesh> mesh = std::make_shared<Mesh>();
mesh->AddSubMesh({ std::move(data), std::move(indices) });
return mesh;
}
std::shared_ptr<Mesh> CreateCapsule(float radius, float mid_height, int radial_segments, int rings)
{
int i, j, prevrow, thisrow, point;
float x, y, z, u, v, w;
float onethird = 1.0f / 3.0f;
float twothirds = 2.0f / 3.0f;
std::vector<Vertex> data;
std::vector<std::uint32_t> indices;
point = 0;
/* top hemisphere */
thisrow = 0;
prevrow = 0;
for(j = 0; j <= (rings + 1); j++)
{
v = float(j);
v /= (rings + 1);
w = std::sin(0.5f * Pi<float>() * v);
y = radius * std::cos(0.5f * Pi<float>() * v);
for(i = 0; i <= radial_segments; i++)
{
u = float(i);
u /= radial_segments;
x = std::sin(u * (Pi<float>() * 2.0f));
z = std::cos(u * (Pi<float>() * 2.0f));
Vec3 p = Vec3f(x * radius * w, y, z * radius * w);
Vertex vertex;
vertex.position = Vec4f(p + Vec3f(0.0f, 0.5f * mid_height, 0.0f), 1.0f);
vertex.normal = p.Normalize();
vertex.uv = Vec2f(u, onethird * v);
data.emplace_back(vertex);
point++;
if(i > 0 && j > 0)
{
indices.push_back(thisrow + i - 1);
indices.push_back(prevrow + i);
indices.push_back(prevrow + i - 1);
indices.push_back(thisrow + i - 1);
indices.push_back(thisrow + i);
indices.push_back(prevrow + i);
};
};
prevrow = thisrow;
thisrow = point;
};
/* cylinder */
thisrow = point;
prevrow = 0;
for(j = 0; j <= (rings + 1); j++)
{
v = float(j);
v /= (rings + 1);
y = mid_height * v;
y = (mid_height * 0.5f) - y;
for(i = 0; i <= radial_segments; i++)
{
u = float(i);
u /= radial_segments;
x = std::sin(u * (Pi<float>() * 2.0f));
z = std::cos(u * (Pi<float>() * 2.0f));
Vec3 p = Vec3f(x * radius, y, z * radius);
Vertex vertex;
vertex.position = p;
// vertex.normal = Vec4f(x, z, 0.0f);
vertex.normal = Vec4f(x, 0.0f, z);
// vertex.uv = Vec2f(u, onethird + (v * onethird));
vertex.uv = Vec2f(u, v * 0.5f);
data.emplace_back(vertex);
point++;
if(i > 0 && j > 0)
{
indices.push_back(thisrow + i - 1);
indices.push_back(prevrow + i);
indices.push_back(prevrow + i - 1);
indices.push_back(thisrow + i - 1);
indices.push_back(thisrow + i);
indices.push_back(prevrow + i);
};
};
prevrow = thisrow;
thisrow = point;
};
/* bottom hemisphere */
thisrow = point;
prevrow = 0;
for(j = 0; j <= (rings + 1); j++)
{
v = float(j);
v /= (rings + 1);
v += 1.0f;
w = std::sin(0.5f * Pi<float>() * v);
y = radius * std::cos(0.5f * Pi<float>() * v);
for(i = 0; i <= radial_segments; i++)
{
float u2 = float(i);
u2 /= radial_segments;
x = std::sin(u2 * (Pi<float>() * 2.0f));
z = std::cos(u2 * (Pi<float>() * 2.0f));
Vec3 p = Vec3f(x * radius * w, y, z * radius * w);
Vertex vertex;
vertex.position = p + Vec3f(0.0f, -0.5f * mid_height, 0.0f);
vertex.normal = p.Normalize();
vertex.uv = Vec2f(u2, twothirds + ((v - 1.0f) * onethird));
data.emplace_back(vertex);
point++;
if(i > 0 && j > 0)
{
indices.push_back(thisrow + i - 1);
indices.push_back(prevrow + i);
indices.push_back(prevrow + i - 1);
indices.push_back(thisrow + i - 1);
indices.push_back(thisrow + i);
indices.push_back(prevrow + i);
};
};
prevrow = thisrow;
thisrow = point;
}
std::shared_ptr<Mesh> mesh = std::make_shared<Mesh>();
mesh->AddSubMesh({ std::move(data), std::move(indices) });
return mesh;
}
}

158
Runtime/Sources/Graphics/Model.cpp git.filemode.normal_file
View File

@@ -0,0 +1,158 @@
#include <Graphics/Model.h>
#include <Graphics/Loaders/OBJ.h>
#include <Renderer/Pipelines/Graphics.h>
#include <Maths/Angles.h>
#include <unordered_map>
namespace Scop
{
Model::Model(std::shared_ptr<Mesh> mesh) : p_mesh(mesh)
{
if(p_mesh)
m_materials.resize(p_mesh->GetSubMeshCount() + 1);
if(!s_default_material)
{
CPUBuffer default_pixels{ kvfFormatSize(VK_FORMAT_R8G8B8A8_SRGB) };
default_pixels.GetDataAs<std::uint32_t>()[0] = 0xFFFFFFFF;
std::shared_ptr<Texture> default_texture = std::make_shared<Texture>(std::move(default_pixels), 1, 1, VK_FORMAT_R8G8B8A8_SRGB);
MaterialTextures textures;
textures.albedo = default_texture;
s_default_material = std::make_shared<Material>(textures);
}
m_materials.back() = s_default_material;
}
void Model::Draw(VkCommandBuffer cmd, std::shared_ptr<DescriptorSet> matrices_set, const GraphicPipeline& pipeline, std::shared_ptr<DescriptorSet> set, std::size_t& drawcalls, std::size_t& polygondrawn, std::size_t frame_index) const
{
if(!p_mesh)
return;
for(std::size_t i = 0; i < GetSubMeshCount(); i++)
{
std::shared_ptr<Material> material;
if(!m_materials[i])
material = m_materials.back();
else
material = m_materials[i];
if(!material->IsSetInit())
material->UpdateDescriptorSet(set);
material->Bind(frame_index, cmd);
std::array<VkDescriptorSet, 2> sets = { matrices_set->GetSet(frame_index), material->GetSet(frame_index) };
RenderCore::Get().vkCmdBindDescriptorSets(cmd, pipeline.GetPipelineBindPoint(), pipeline.GetPipelineLayout(), 0, sets.size(), sets.data(), 0, nullptr);
p_mesh->Draw(cmd, drawcalls, polygondrawn, i);
}
}
RadianAnglef GetAngleBetweenVectors(const Vec3f& a, const Vec3f& b) noexcept
{
float cosine_theta = (a.DotProduct(b)) / (a.GetLength() * b.GetLength());
RadianAnglef angle(std::acos(cosine_theta));
return angle;
}
Model LoadModelFromObjFile(std::filesystem::path path) noexcept
{
auto obj_data = LoadObjFromFile(path);
if(!obj_data)
return { nullptr };
TesselateObjData(*obj_data);
ObjModel obj_model = ConvertObjDataToObjModel(*obj_data);
std::shared_ptr<Mesh> mesh = std::make_shared<Mesh>();
float min_x = std::numeric_limits<float>::max(), max_x = std::numeric_limits<float>::lowest();
float min_y = std::numeric_limits<float>::max(), max_y = std::numeric_limits<float>::lowest();
float min_z = std::numeric_limits<float>::max(), max_z = std::numeric_limits<float>::lowest();
bool needs_to_generate_normals = obj_model.normal.empty();
std::unordered_map<std::string, std::vector<Vec3f>> generated_normals;
if(needs_to_generate_normals)
{
for(auto& [group, faces] : obj_model.faces)
{
generated_normals[group] = std::vector<Vec3f>(faces.size(), Vec3f{});
for(std::size_t i = 0; i < faces.size(); i += 3)
{
Vec3f vec_a{ obj_model.vertex[faces[i + 1]] - obj_model.vertex[faces[i]] };
Vec3f vec_b{ obj_model.vertex[faces[i + 2]] - obj_model.vertex[faces[i]] };
Vec3f normal = vec_a.CrossProduct(vec_b).Normalize();
generated_normals[group][i + 0] = normal;
generated_normals[group][i + 1] = normal;
generated_normals[group][i + 2] = normal;
}
}
}
for(auto& [group, faces] : obj_model.faces)
{
std::vector<Vertex> vertices;
std::vector<std::uint32_t> indices;
for(std::size_t i = 0; i < faces.size(); i++)
{
min_x = std::min(obj_model.vertex[faces[i]].x, min_x);
min_y = std::min(obj_model.vertex[faces[i]].y, min_y);
min_z = std::min(obj_model.vertex[faces[i]].z, min_z);
max_x = std::max(obj_model.vertex[faces[i]].x, max_x);
max_y = std::max(obj_model.vertex[faces[i]].y, max_y);
max_z = std::max(obj_model.vertex[faces[i]].z, max_z);
Vec4f color{};
switch(i % 10)
{
case 0: color = Vec4f{ 1.0f, 0.0f, 1.0f, 1.0f }; break;
case 1: color = Vec4f{ 1.0f, 1.0f, 0.0f, 1.0f }; break;
case 2: color = Vec4f{ 1.0f, 0.5f, 0.0f, 1.0f }; break;
case 3: color = Vec4f{ 1.0f, 0.0f, 0.0f, 1.0f }; break;
case 4: color = Vec4f{ 0.2f, 0.0f, 0.8f, 1.0f }; break;
case 5: color = Vec4f{ 0.0f, 1.0f, 1.0f, 1.0f }; break;
case 6: color = Vec4f{ 0.0f, 1.0f, 0.0f, 1.0f }; break;
case 7: color = Vec4f{ 0.0f, 0.0f, 1.0f, 1.0f }; break;
case 8: color = Vec4f{ 0.3f, 0.0f, 0.4f, 1.0f }; break;
default: color = Vec4f{ 1.0f, 1.0f, 1.0f, 1.0f }; break;
}
Vec3f normal{};
if(needs_to_generate_normals)
{
normal = generated_normals[group][i];
for(std::size_t j = 0; j < faces.size(); j++)
{
if(faces[j] == faces[i] && i != j)
{
RadianAnglef angle = GetAngleBetweenVectors(generated_normals[group][i], generated_normals[group][j]);
if(angle.ToDegrees() < 89.0f)
normal += generated_normals[group][j];
}
}
}
else
normal = obj_model.normal[faces[i]];
Vertex v(
Vec4f{
obj_model.vertex[faces[i]],
1.0f
},
color,
Vec4f{
normal.Normalize(),
1.0f
},
(obj_model.tex_coord.empty() ?
Vec2f{ (obj_model.vertex[faces[i]].x - min_x) / (max_x - min_x), 1.0f - ((obj_model.vertex[faces[i]].y - min_y) / (max_y - min_y)) }
:
obj_model.tex_coord[faces[i]]
)
);
indices.push_back(vertices.size());
vertices.push_back(std::move(v));
}
mesh->AddSubMesh({ vertices, indices });
}
Model model(mesh);
model.m_center = Vec3f{ (min_x + max_x) / 2.0f, (min_y + max_y) / 2.0f, (min_z + max_z) / 2.0f };
return model;
}
}

223
Runtime/Sources/Graphics/Scene.cpp git.filemode.normal_file
View File

@@ -0,0 +1,223 @@
#include <Graphics/Scene.h>
#include <Renderer/Renderer.h>
#include <Renderer/RenderCore.h>
#include <Platform/Inputs.h>
#include <Core/Logs.h>
#include <Renderer/ViewerData.h>
#include <Core/EventBus.h>
#include <Core/Engine.h>
#include <Graphics/DogicaTTF.h>
#include <cstring>
namespace Scop
{
Scene::Scene(std::string_view name, SceneDescriptor desc)
: m_name(name), m_descriptor(std::move(desc)), p_parent(nullptr)
{
LoadFont("default", 6.0f);
}
Scene::Scene(std::string_view name, SceneDescriptor desc, NonOwningPtr<Scene> parent)
: m_name(name), m_descriptor(std::move(desc)), p_parent(parent)
{
LoadFont("default", 6.0f);
}
Actor& Scene::CreateActor(Model model) noexcept
{
UUID uuid = UUID();
return m_actors.try_emplace(uuid, uuid, std::move(model)).first->second;
}
Actor& Scene::CreateActor(std::string_view name, Model model)
{
UUID uuid = UUID();
return m_actors.try_emplace(uuid, uuid, std::move(model)).first->second;
}
Narrator& Scene::CreateNarrator() noexcept
{
UUID uuid = UUID();
return m_narrators.try_emplace(uuid, uuid).first->second;
}
Narrator& Scene::CreateNarrator(std::string_view name)
{
UUID uuid = UUID();
return m_narrators.try_emplace(uuid, uuid).first->second;
}
Sprite& Scene::CreateSprite(std::shared_ptr<Texture> texture) noexcept
{
UUID uuid = UUID();
return m_sprites.try_emplace(uuid, uuid, texture).first->second;
}
Sprite& Scene::CreateSprite(std::string_view name, std::shared_ptr<Texture> texture)
{
UUID uuid = UUID();
return m_sprites.try_emplace(uuid, uuid, texture).first->second;
}
Text& Scene::CreateText(std::string text) noexcept
{
UUID uuid = UUID();
return m_texts.try_emplace(uuid, uuid, std::move(text), p_bound_font).first->second;
}
Text& Scene::CreateText(std::string_view name, std::string text)
{
UUID uuid = UUID();
return m_texts.try_emplace(uuid, uuid, std::move(text), p_bound_font).first->second;
}
void Scene::LoadFont(std::filesystem::path path, float scale)
{
std::shared_ptr<Font> font = m_fonts_registry.GetFont(path, scale);
if(!font)
{
if(path.string() == "default")
font = std::make_shared<Font>("default", dogica_ttf, scale);
else
font = std::make_shared<Font>(std::move(path), scale);
font->BuildFont();
m_fonts_registry.RegisterFont(font);
}
p_bound_font = font;
}
void Scene::RemoveActor(Actor& actor) noexcept
{
auto it = m_actors.find(actor.GetUUID());
if(it == m_actors.end())
{
Error("Actor not found");
return;
}
m_actors.erase(it);
}
void Scene::RemoveNarrator(Narrator& narrator) noexcept
{
auto it = m_narrators.find(narrator.GetUUID());
if(it == m_narrators.end())
{
Error("Narrator not found");
return;
}
m_narrators.erase(it);
}
void Scene::RemoveSprite(Sprite& sprite) noexcept
{
auto it = m_sprites.find(sprite.GetUUID());
if(it == m_sprites.end())
{
Error("Sprite not found");
return;
}
m_sprites.erase(it);
}
void Scene::RemoveText(Text& text) noexcept
{
auto it = m_texts.find(text.GetUUID());
if(it == m_texts.end())
{
Error("Text not found");
return;
}
m_texts.erase(it);
}
void Scene::SwitchToChild(std::string_view name) const noexcept
{
auto it = std::find_if(m_scene_children.begin(), m_scene_children.end(), [name](const Scene& scene){ return name == scene.GetName(); });
if(it == m_scene_children.end())
{
Error("Cannot switch to scene '%', scene not found in children of '%'", name, m_name);
return;
}
ScopEngine::Get().SwitchToScene(const_cast<Scene*>(&(*it)));
}
void Scene::SwitchToParent() const noexcept
{
ScopEngine::Get().SwitchToScene(p_parent);
}
void Scene::Init(NonOwningPtr<Renderer> renderer)
{
std::function<void(const EventBase&)> functor = [this, renderer](const EventBase& event)
{
if(event.What() == Event::ResizeEventCode)
{
m_depth.Destroy();
m_depth.Init(renderer->GetSwapchain().GetSwapchainImages().back().GetWidth(), renderer->GetSwapchain().GetSwapchainImages().back().GetHeight(), false, m_name + "_depth");
m_depth.CreateSampler();
}
if(event.What() == Event::ResizeEventCode || event.What() == Event::SceneHasChangedEventCode)
m_pipeline.Destroy(); // Ugly but f*ck off
};
EventBus::RegisterListener({ functor, m_name + std::to_string(reinterpret_cast<std::uintptr_t>(this)) });
if(m_descriptor.post_process_shader)
{
m_post_process.set = RenderCore::Get().GetDescriptorPoolManager().GetAvailablePool().RequestDescriptorSet(m_descriptor.post_process_shader->GetShaderLayout().set_layouts.at(0), ShaderType::Fragment);
m_post_process.data_buffer = std::make_shared<UniformBuffer>();
m_post_process.data_buffer->Init(m_descriptor.post_process_data_size, m_name + "_post_process_data_buffer");
}
m_post_process.data.Allocate(m_descriptor.post_process_data_size);
auto vertex_shader = RenderCore::Get().GetDefaultVertexShader();
m_depth.Init(renderer->GetSwapchain().GetSwapchainImages().back().GetWidth(), renderer->GetSwapchain().GetSwapchainImages().back().GetHeight(), false, m_name + "_depth");
m_depth.CreateSampler();
m_forward.matrices_buffer = std::make_shared<UniformBuffer>();
m_forward.matrices_buffer->Init(sizeof(ViewerData), m_name + "_matrice_buffer");
m_forward.matrices_set = RenderCore::Get().GetDescriptorPoolManager().GetAvailablePool().RequestDescriptorSet(vertex_shader->GetShaderLayout().set_layouts.at(0), ShaderType::Vertex);
for(std::size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++)
{
m_forward.matrices_set->SetUniformBuffer(i, 0, m_forward.matrices_buffer->Get(i));
m_forward.matrices_set->Update(i);
}
m_forward.albedo_set = RenderCore::Get().GetDescriptorPoolManager().GetAvailablePool().RequestDescriptorSet(m_descriptor.fragment_shader->GetShaderLayout().set_layouts.at(1), ShaderType::Fragment);
for(auto& child : m_scene_children)
child.Init(renderer);
}
void Scene::Update(Inputs& input, float timestep, float aspect)
{
for(auto& [_, actor] : m_actors)
actor.Update(this, input, timestep);
for(auto& [_, narrator] : m_narrators)
narrator.Update(this, input, timestep);
for(auto& [_, sprite] : m_sprites)
sprite.Update(this, input, timestep);
if(m_descriptor.camera)
m_descriptor.camera->Update(input, aspect, timestep);
}
void Scene::Destroy()
{
RenderCore::Get().WaitDeviceIdle();
p_skybox.reset();
m_depth.Destroy();
m_actors.clear();
m_narrators.clear();
m_sprites.clear();
m_pipeline.Destroy();
m_descriptor.fragment_shader.reset();
m_descriptor.post_process_shader.reset();
m_forward.matrices_buffer->Destroy();
if(m_post_process.data_buffer)
m_post_process.data_buffer->Destroy();
m_fonts_registry.Reset();
for(auto& child : m_scene_children)
child.Destroy();
}
}

41
Runtime/Sources/Graphics/Sprite.cpp git.filemode.normal_file
View File

@@ -0,0 +1,41 @@
#include <Graphics/Sprite.h>
#include <Core/Script.h>
#include <Renderer/Image.h>
#include <Graphics/MeshFactory.h>
#include <Core/Logs.h>
#include <Core/UUID.h>
namespace Scop
{
Sprite::Sprite(std::shared_ptr<Texture> texture)
{
Verify((bool)texture, "Sprite: invalid texture");
m_uuid = UUID();
p_mesh = CreateQuad(0, 0, texture->GetWidth(), texture->GetHeight());
p_texture = texture;
if(p_script)
p_script->OnInit(this);
}
Sprite::Sprite(std::uint64_t uuid, std::shared_ptr<Texture> texture)
{
Verify((bool)texture, "Sprite: invalid texture");
m_uuid = uuid;
p_mesh = CreateQuad(0, 0, texture->GetWidth(), texture->GetHeight());
p_texture = texture;
if(p_script)
p_script->OnInit(this);
}
void Sprite::Update(NonOwningPtr<Scene> scene, Inputs& input, float delta)
{
if(p_script)
p_script->OnUpdate(scene, this, input, delta);
}
Sprite::~Sprite()
{
if(p_script)
p_script->OnQuit(this);
}
}

48
Runtime/Sources/Graphics/Text.cpp git.filemode.normal_file
View File

@@ -0,0 +1,48 @@
#include <Graphics/Text.h>
#include <Renderer/Vertex.h>
#include <vector>
namespace Scop
{
Text::Text(std::uint64_t uuid, const std::string& text, std::shared_ptr<Font> font) : m_uuid(uuid)
{
Assert(font != nullptr, "invalid font");
std::vector<Vertex> vertex_data;
std::vector<std::uint32_t> index_data;
float stb_x = 0.0f;
float stb_y = 0.0f;
const auto& char_data = font->GetCharData();
for(char c : text)
{
if(c < 32)
continue;
stbtt_aligned_quad q;
stbtt_GetPackedQuad(char_data.data(), RANGE, RANGE, c - 32, &stb_x, &stb_y, &q, 1);
std::size_t index = vertex_data.size();
vertex_data.emplace_back(Vec4f{ q.x0, q.y0, 0.0f, 1.0f }, Vec4f{ 1.0f }, -Vec2f{ q.s0, -q.t0 });
vertex_data.emplace_back(Vec4f{ q.x1, q.y0, 0.0f, 1.0f }, Vec4f{ 1.0f }, -Vec2f{ q.s1, -q.t0 });
vertex_data.emplace_back(Vec4f{ q.x1, q.y1, 0.0f, 1.0f }, Vec4f{ 1.0f }, -Vec2f{ q.s1, -q.t1 });
vertex_data.emplace_back(Vec4f{ q.x0, q.y1, 0.0f, 1.0f }, Vec4f{ 1.0f }, -Vec2f{ q.s0, -q.t1 });
index_data.push_back(index + 0);
index_data.push_back(index + 1);
index_data.push_back(index + 2);
index_data.push_back(index + 2);
index_data.push_back(index + 3);
index_data.push_back(index + 0);
}
std::shared_ptr<Mesh> mesh = std::make_shared<Mesh>();
mesh->AddSubMesh({ std::move(vertex_data), std::move(index_data) });
p_mesh = mesh;
p_font = font;
m_text = text;
}
}