try getting normal maps to work

This commit is contained in:
Bailey Harrison 2023-11-05 01:04:05 +00:00
parent 53804696b3
commit b58d343c8d
41 changed files with 855 additions and 729 deletions

View File

@ -199,7 +199,7 @@ target_include_directories(${PROJECT_NAME} SYSTEM PUBLIC dependencies/glm)
# spdlog # spdlog
set(SPDLOG_BUILD_SHARED OFF CACHE INTERNAL "" FORCE) set(SPDLOG_BUILD_SHARED OFF CACHE INTERNAL "" FORCE)
set(SPDLOG_SYSTEM_INCLUDES ON CACHE INTERNAL "" FORCE)
set(BUILD_SHARED_LIBS OFF) set(BUILD_SHARED_LIBS OFF)
add_subdirectory(dependencies/spdlog) add_subdirectory(dependencies/spdlog) # automatically calls target_include_directories
target_link_libraries(${PROJECT_NAME} PUBLIC spdlog) target_link_libraries(${PROJECT_NAME} PUBLIC spdlog)
target_include_directories(${PROJECT_NAME} SYSTEM PUBLIC dependencies/spdlog/include)

View File

@ -9,8 +9,8 @@
namespace engine { namespace engine {
struct MeshRenderableComponent { struct MeshRenderableComponent {
std::shared_ptr<resources::Mesh> mesh; std::shared_ptr<Mesh> mesh;
std::shared_ptr<resources::Material> material; std::shared_ptr<Material> material;
}; };
} // namespace engine } // namespace engine

View File

@ -33,7 +33,7 @@ class Renderer {
void PreRender(bool window_is_resized, glm::mat4 camera_transform); void PreRender(bool window_is_resized, glm::mat4 camera_transform);
// staticList can be nullptr to render nothing // staticList can be nullptr to render nothing
void Render(const RenderList& static_list, const RenderList& dynamic_list); void Render(const RenderList* static_list, const RenderList* dynamic_list);
// getters // getters
@ -78,7 +78,10 @@ class Renderer {
*/ */
// ALL fragment shaders must begin with: // ALL fragment shaders must begin with:
/* /*
layout(set = 2, binding = 0) uniform sampler2D materialSetSampler; layout(set = 2, binding = 0) uniform sampler2D materialSetAlbedoSampler;
layout(set = 2, binding = 1) uniform sampler2D materialSetNormalSampler;
layout(set = 2, binding = 2) uniform sampler2D materialSetOcclusionSampler;
layout(set = 2, binding = 3) uniform sampler2D materialSetMetallicRoughnessSampler;
*/ */
// in vertex shader // in vertex shader

View File

@ -9,7 +9,6 @@
#include <stb_truetype.h> #include <stb_truetype.h>
namespace engine { namespace engine {
namespace resources {
class Font { class Font {
public: public:
@ -31,7 +30,6 @@ class Font {
int GetGlyphIndex(int unicode_codepoint); int GetGlyphIndex(int unicode_codepoint);
}; };
} // namespace resources
} // namespace engine } // namespace engine
#endif #endif

View File

@ -6,26 +6,37 @@
#include "resources/shader.h" #include "resources/shader.h"
#include "resources/texture.h" #include "resources/texture.h"
// a material is just a shader with assigned textures/parameters
namespace engine { namespace engine {
namespace resources {
// copyable // copyable
class Material { class Material {
public: public:
Material(std::shared_ptr<Shader> shader); Material(Renderer* renderer, std::shared_ptr<engine::Shader> shader);
~Material() = default; ~Material();
Material(const Material&);
Material& operator=(const Material&) = delete; Material& operator=(const Material&) = delete;
auto GetShader() { return shader_.get(); } void SetAlbedoTexture(std::shared_ptr<Texture> texture);
void SetNormalTexture(std::shared_ptr<Texture> texture);
void SetOcclusionTexture(std::shared_ptr<Texture> texture);
void SetMetallicRoughnessTexture(std::shared_ptr<Texture> texture);
std::shared_ptr<Texture> texture_; const gfx::DescriptorSet* GetDescriptorSet() { return material_set_; }
Shader* GetShader() { return shader_.get(); }
private: private:
const std::shared_ptr<Shader> shader_; const std::shared_ptr<Shader> shader_;
std::shared_ptr<Texture> texture_albedo_;
std::shared_ptr<Texture> texture_normal_;
std::shared_ptr<Texture> texture_occlusion_;
std::shared_ptr<Texture> texture_metallic_roughness_;
const gfx::DescriptorSet* material_set_ = nullptr;
Renderer* const renderer_;
}; };
} // namespace resources
} // namespace engine } // namespace engine
#endif #endif

View File

@ -3,6 +3,7 @@
#include <glm/vec2.hpp> #include <glm/vec2.hpp>
#include <glm/vec3.hpp> #include <glm/vec3.hpp>
#include <glm/vec4.hpp>
#include <vector> #include <vector>
#include "gfx.h" #include "gfx.h"
@ -13,13 +14,13 @@ namespace engine {
struct Vertex { struct Vertex {
glm::vec3 pos; glm::vec3 pos;
glm::vec3 norm; glm::vec3 norm;
glm::vec4 tangent; // w component flips binormal if -1. w should be 1 or -1
glm::vec2 uv; glm::vec2 uv;
}; };
} // namespace engine } // namespace engine
namespace engine { namespace engine {
namespace resources {
class Mesh { class Mesh {
public: public:
@ -48,7 +49,6 @@ class Mesh {
const std::vector<uint32_t>& indices); const std::vector<uint32_t>& indices);
}; };
} // namespace resources
} // namespace engine } // namespace engine
#endif #endif

View File

@ -1,12 +1,10 @@
#ifndef ENGINE_INCLUDE_RESOURCES_SHADER_H_ #pragma once
#define ENGINE_INCLUDE_RESOURCES_SHADER_H_
#include "application.h" #include "application.h"
#include "gfx.h" #include "gfx.h"
#include "gfx_device.h" #include "gfx_device.h"
namespace engine { namespace engine {
namespace resources {
class Shader { class Shader {
public: public:
@ -43,7 +41,4 @@ class Shader {
const int render_order_; const int render_order_;
}; };
} // namespace resources
} // namespace engine } // namespace engine
#endif

View File

@ -7,7 +7,6 @@
#include "gfx_device.h" #include "gfx_device.h"
namespace engine { namespace engine {
namespace resources {
class Texture { class Texture {
public: public:
@ -18,25 +17,23 @@ class Texture {
kAnisotropic, kAnisotropic,
}; };
Texture(Renderer* renderer, const std::string& path, Texture(Renderer* renderer, const uint8_t* bitmap, int width, int height, Filtering filtering);
Filtering filtering);
Texture(Renderer* renderer, const uint8_t* bitmap, int width, int height,
Filtering filtering);
~Texture(); ~Texture();
Texture(const Texture&) = delete; Texture(const Texture&) = delete;
Texture& operator=(const Texture&) = delete; Texture& operator=(const Texture&) = delete;
const gfx::Image* GetImage() { return image_; } const gfx::Image* GetImage() { return image_; }
const gfx::DescriptorSet* GetDescriptorSet() { return descriptor_set_; } const gfx::Sampler* GetSampler() { return sampler_; }
private: private:
GFXDevice* gfx_; GFXDevice* gfx_;
const gfx::Image* image_; const gfx::Image* image_;
const gfx::DescriptorSet* descriptor_set_; const gfx::Sampler* sampler_; // not owned by Texture, owned by Renderer
}; };
} // namespace resources std::unique_ptr<Texture> LoadTextureFromFile(const std::string& path, Texture::Filtering filtering, Renderer* renderer);
} // namespace engine } // namespace engine
#endif #endif

View File

@ -21,6 +21,30 @@ class SceneManager {
// creates an empty scene and sets it as active // creates an empty scene and sets it as active
Scene* CreateEmptyScene(); Scene* CreateEmptyScene();
// nullptr deactivates the active scene
void SetActiveScene(Scene* scene)
{
if (scene == nullptr) {
active_scene_index_ = -1;
}
else {
// linear search for scene
int index = 0;
for (const auto& unique_scene : scenes_) {
if (unique_scene.get() == scene) {
break;
}
++index;
}
if (index >= scenes_.size()) {
throw std::runtime_error("Failed to find active scene!");
}
else {
active_scene_index_ = index;
}
}
}
// returns active scene, nullptr if no scene active // returns active scene, nullptr if no scene active
Scene* UpdateActiveScene(float ts); Scene* UpdateActiveScene(float ts);
Scene* GetActiveScene() { return scenes_.at(active_scene_index_).get(); } Scene* GetActiveScene() { return scenes_.at(active_scene_index_).get(); }

View File

@ -1,5 +1,4 @@
#ifndef ENGINE_INCLUDE_SYSTEMS_MESH_RENDER_SYSTEM_H_ #pragma once
#define ENGINE_INCLUDE_SYSTEMS_MESH_RENDER_SYSTEM_H_
#include <glm/mat4x4.hpp> #include <glm/mat4x4.hpp>
@ -13,7 +12,7 @@ struct RenderListEntry {
const gfx::Pipeline* pipeline; const gfx::Pipeline* pipeline;
const gfx::Buffer* vertex_buffer; const gfx::Buffer* vertex_buffer;
const gfx::Buffer* index_buffer; const gfx::Buffer* index_buffer;
const gfx::DescriptorSet* base_colour_texture; const gfx::DescriptorSet* material_set;
glm::mat4 model_matrix; glm::mat4 model_matrix;
uint32_t index_count; uint32_t index_count;
}; };
@ -44,5 +43,3 @@ class MeshRenderSystem : public System {
}; };
} // namespace engine } // namespace engine
#endif

View File

@ -14,7 +14,7 @@ std::unique_ptr<std::vector<uint8_t>> ReadBinaryFile(const std::string& path);
// Read an image file into a vector byte buffer. PNG and JPG support at a // Read an image file into a vector byte buffer. PNG and JPG support at a
// minimum. Output format is R8G8B8A8_UINT // minimum. Output format is R8G8B8A8_UINT
std::unique_ptr<std::vector<uint8_t>> ReadImageFile(const std::string& path, std::unique_ptr<std::vector<uint8_t>> ReadImageFile(const std::string& path,
int* width, int* height); int& width, int& height);
} // namespace util } // namespace util
} // namespace engine } // namespace engine

View File

@ -0,0 +1,42 @@
#version 450
layout(set = 2, binding = 0) uniform sampler2D materialSetAlbedoSampler;
layout(set = 2, binding = 1) uniform sampler2D materialSetNormalSampler;
layout(set = 2, binding = 2) uniform sampler2D materialSetOcclusionSampler;
layout(set = 2, binding = 3) uniform sampler2D materialSetMetallicRoughnessSampler;
layout(location = 0) in vec3 fragPos;
layout(location = 1) in vec3 fragNorm;
layout(location = 2) in vec2 fragUV;
layout(location = 3) in vec3 fragViewPos;
layout(location = 4) in vec3 fragLightPos;
layout(location = 5) in mat3 fragTBN;
layout(location = 0) out vec4 outColor;
void main() {
// constants
vec3 lightColor = vec3(1.0, 1.0, 1.0);
vec3 ambientColor = vec3(1.0, 1.0, 1.0);
float ambientStrength = 0.05;
vec3 emission = vec3(0.0, 0.0, 0.0);
vec3 baseColor = vec3(texture(materialSetAlbedoSampler, fragUV));
vec3 norm = vec3(texture(materialSetNormalSampler, fragUV));
norm = normalize(norm * 2.0 - 1.0);
vec3 lightDir = fragTBN * normalize(fragLightPos - fragPos);
vec3 viewDir = fragTBN * normalize(fragViewPos - fragPos);
vec3 diffuse = max(dot(norm, lightDir), 0.0) * lightColor;
vec3 ambient = ambientColor * ambientStrength;
vec3 halfwayDir = normalize(lightDir + viewDir);
float spec = pow(max(dot(norm, halfwayDir), 0.0), 32.0);
vec3 specular = spec * lightColor;
vec3 lighting = min(diffuse + ambient + specular, 1.0);
outColor = min( ( vec4(baseColor, 1.0) ) * vec4(lighting + emission, 1.0), vec4(1.0));
}

View File

@ -0,0 +1,43 @@
#version 450
layout(set = 0, binding = 0) uniform GlobalSetUniformBuffer {
mat4 proj;
} globalSetUniformBuffer;
layout(set = 1, binding = 0) uniform FrameSetUniformBuffer {
mat4 view;
} frameSetUniformBuffer;
layout( push_constant ) uniform Constants {
mat4 model;
} constants;
layout(location = 0) in vec3 inPosition;
layout(location = 1) in vec3 inNorm;
layout(location = 2) in vec4 inTangent;
layout(location = 3) in vec2 inUV;
layout(location = 0) out vec3 fragPos;
layout(location = 1) out vec3 fragNorm;
layout(location = 2) out vec2 fragUV;
layout(location = 3) out vec3 fragViewPos;
layout(location = 4) out vec3 fragLightPos;
layout(location = 5) out mat3 fragTBN;
void main() {
gl_Position = globalSetUniformBuffer.proj * frameSetUniformBuffer.view * constants.model * vec4(inPosition, 1.0);
mat3 normalMatrix = mat3(transpose(inverse(constants.model)));
fragPos = vec3(constants.model * vec4(inPosition, 1.0));
fragNorm = normalize(normalMatrix * inNorm);
fragUV = inUV;
fragViewPos = vec3(inverse(frameSetUniformBuffer.view) * vec4(0.0, 0.0, 0.0, 1.0));
fragLightPos = vec3(2000.0, -2000.0, 2000.0);
vec3 T = normalize(normalMatrix * inTangent.xyz);
vec3 B = cross(fragNorm, T) * inTangent.w; // from unity docs, w flips the binormal
fragTBN = transpose(mat3(T, B, fragNorm));
gl_Position.y *= -1.0;
}

View File

@ -14,7 +14,8 @@ layout( push_constant ) uniform Constants {
layout(location = 0) in vec3 inPosition; layout(location = 0) in vec3 inPosition;
layout(location = 1) in vec3 inNorm; layout(location = 1) in vec3 inNorm;
layout(location = 2) in vec2 inUV; layout(location = 2) in vec4 inTangent;
layout(location = 3) in vec2 inUV;
layout(location = 0) out vec2 fragUV; layout(location = 0) out vec2 fragUV;

View File

@ -12,7 +12,8 @@ layout(set = 0, binding = 0) uniform SetZeroBuffer {
layout(location = 0) in vec3 inPosition; layout(location = 0) in vec3 inPosition;
layout(location = 1) in vec3 inNorm; layout(location = 1) in vec3 inNorm;
layout(location = 2) in vec2 inUV; layout(location = 2) in vec4 inTangent;
layout(location = 3) in vec2 inUV;
layout(location = 0) out vec3 fragNorm; layout(location = 0) out vec3 fragNorm;

View File

@ -12,7 +12,8 @@ layout(set = 0, binding = 0) uniform SetZeroBuffer {
layout(location = 0) in vec3 inPosition; layout(location = 0) in vec3 inPosition;
layout(location = 1) in vec3 inNorm; layout(location = 1) in vec3 inNorm;
layout(location = 2) in vec2 inUV; layout(location = 2) in vec4 inTangent;
layout(location = 3) in vec2 inUV;
layout(location = 0) out vec2 fragUV; layout(location = 0) out vec2 fragUV;

View File

@ -1,11 +1,14 @@
#version 450 #version 450
layout(set = 2, binding = 0) uniform sampler2D materialSetSampler; layout(set = 2, binding = 0) uniform sampler2D materialSetAlbedoSampler;
layout(set = 2, binding = 1) uniform sampler2D materialSetNormalSampler;
layout(set = 2, binding = 2) uniform sampler2D materialSetOcclusionSampler;
layout(set = 2, binding = 3) uniform sampler2D materialSetMetallicRoughnessSampler;
layout(location = 0) in vec2 fragUV; layout(location = 0) in vec2 fragUV;
layout(location = 0) out vec4 outColor; layout(location = 0) out vec4 outColor;
void main() { void main() {
outColor = texture(materialSetSampler, fragUV); outColor = texture(materialSetAlbedoSampler, fragUV);
} }

View File

@ -13,7 +13,9 @@ layout( push_constant ) uniform Constants {
} constants; } constants;
layout(location = 0) in vec3 inPosition; layout(location = 0) in vec3 inPosition;
layout(location = 2) in vec2 inUV; layout(location = 1) in vec3 inNorm;
layout(location = 2) in vec4 inTangent;
layout(location = 3) in vec2 inUV;
layout(location = 0) out vec2 fragUV; layout(location = 0) out vec2 fragUV;

View File

@ -1,6 +1,9 @@
#version 450 #version 450
layout(set = 2, binding = 0) uniform sampler2D materialSetSampler; layout(set = 2, binding = 0) uniform sampler2D materialSetAlbedoSampler;
layout(set = 2, binding = 1) uniform sampler2D materialSetNormalSampler;
layout(set = 2, binding = 2) uniform sampler2D materialSetOcclusionSampler;
layout(set = 2, binding = 3) uniform sampler2D materialSetMetallicRoughnessSampler;
layout(location = 0) in vec3 fragPos; layout(location = 0) in vec3 fragPos;
layout(location = 1) in vec3 fragNorm; layout(location = 1) in vec3 fragNorm;
@ -15,7 +18,7 @@ void main() {
vec3 lightColor = vec3(1.0, 1.0, 1.0); vec3 lightColor = vec3(1.0, 1.0, 1.0);
vec3 ambientColor = vec3(1.0, 1.0, 1.0); vec3 ambientColor = vec3(1.0, 1.0, 1.0);
float ambientStrength = 0.05; float ambientStrength = 0.05;
vec3 baseColor = vec3(texture(materialSetSampler, fragUV)); vec3 baseColor = vec3(texture(materialSetAlbedoSampler, fragUV));
vec3 emission = vec3(0.0, 0.0, 0.0); vec3 emission = vec3(0.0, 0.0, 0.0);
// code // code

View File

@ -14,7 +14,8 @@ layout( push_constant ) uniform Constants {
layout(location = 0) in vec3 inPosition; layout(location = 0) in vec3 inPosition;
layout(location = 1) in vec3 inNorm; layout(location = 1) in vec3 inNorm;
layout(location = 2) in vec2 inUV; layout(location = 2) in vec4 inTangent;
layout(location = 3) in vec2 inUV;
layout(location = 0) out vec3 fragPos; layout(location = 0) out vec3 fragPos;
layout(location = 1) out vec3 fragNorm; layout(location = 1) out vec3 fragNorm;

View File

@ -83,11 +83,11 @@ Application::Application(const char* appName, const char* appVersion, gfx::Graph
resources_path_ = getResourcesPath(); resources_path_ = getResourcesPath();
// register resource managers // register resource managers
RegisterResourceManager<resources::Mesh>(); RegisterResourceManager<Mesh>();
RegisterResourceManager<resources::Material>(); RegisterResourceManager<Material>();
RegisterResourceManager<resources::Texture>(); RegisterResourceManager<Texture>();
RegisterResourceManager<resources::Shader>(); RegisterResourceManager<Shader>();
RegisterResourceManager<resources::Font>(); RegisterResourceManager<Font>();
im_gui_things.context = ImGui::CreateContext(); im_gui_things.context = ImGui::CreateContext();
// ImGuiIO& io = ImGui::GetIO() // ImGuiIO& io = ImGui::GetIO()
@ -97,58 +97,78 @@ Application::Application(const char* appName, const char* appVersion, gfx::Graph
/* default fonts */ /* default fonts */
{ {
auto monoFont = std::make_unique<resources::Font>(GetResourcePath("engine/fonts/mono.ttf")); auto monoFont = std::make_unique<Font>(GetResourcePath("engine/fonts/mono.ttf"));
GetResourceManager<resources::Font>()->AddPersistent("builtin.mono", std::move(monoFont)); GetResourceManager<Font>()->AddPersistent("builtin.mono", std::move(monoFont));
} }
/* default shaders */ /* default shaders */
{ {
resources::Shader::VertexParams vertParams{}; Shader::VertexParams vertParams{};
vertParams.has_normal = true; vertParams.has_normal = true;
vertParams.has_tangent = true;
vertParams.has_uv0 = true; vertParams.has_uv0 = true;
resources::Shader::ShaderSettings shaderSettings{}; Shader::ShaderSettings shaderSettings{};
shaderSettings.vertexParams = vertParams; shaderSettings.vertexParams = vertParams;
shaderSettings.alpha_blending = false; shaderSettings.alpha_blending = false;
shaderSettings.cull_backface = true; shaderSettings.cull_backface = true;
shaderSettings.write_z = true; shaderSettings.write_z = true;
shaderSettings.render_order = 0; shaderSettings.render_order = 0;
auto texturedShader = std::make_unique<resources::Shader>(renderer(), GetResourcePath("engine/shaders/standard.vert").c_str(), auto texturedShader = std::make_unique<Shader>(renderer(), GetResourcePath("engine/shaders/standard.vert").c_str(),
GetResourcePath("engine/shaders/standard.frag").c_str(), shaderSettings); GetResourcePath("engine/shaders/standard.frag").c_str(), shaderSettings);
GetResourceManager<resources::Shader>()->AddPersistent("builtin.standard", std::move(texturedShader)); GetResourceManager<Shader>()->AddPersistent("builtin.standard", std::move(texturedShader));
} }
{ {
resources::Shader::VertexParams vertParams{}; Shader::VertexParams vertParams{};
vertParams.has_normal = true; vertParams.has_normal = true;
vertParams.has_tangent = true;
vertParams.has_uv0 = true; vertParams.has_uv0 = true;
resources::Shader::ShaderSettings shaderSettings{}; Shader::ShaderSettings shaderSettings{};
shaderSettings.vertexParams = vertParams; shaderSettings.vertexParams = vertParams;
shaderSettings.alpha_blending = false; shaderSettings.alpha_blending = false;
shaderSettings.cull_backface = true; shaderSettings.cull_backface = true;
shaderSettings.write_z = true; shaderSettings.write_z = true;
shaderSettings.render_order = 0; shaderSettings.render_order = 0;
auto skyboxShader = std::make_unique<resources::Shader>(renderer(), GetResourcePath("engine/shaders/skybox.vert").c_str(), auto fancyShader = std::make_unique<Shader>(renderer(), GetResourcePath("engine/shaders/fancy.vert").c_str(),
GetResourcePath("engine/shaders/skybox.frag").c_str(), shaderSettings); GetResourcePath("engine/shaders/fancy.frag").c_str(), shaderSettings);
GetResourceManager<resources::Shader>()->AddPersistent("builtin.skybox", std::move(skyboxShader)); GetResourceManager<Shader>()->AddPersistent("builtin.fancy", std::move(fancyShader));
} }
if (0) { {
resources::Shader::VertexParams vertParams{}; Shader::VertexParams vertParams{};
vertParams.has_normal = true; vertParams.has_normal = true;
vertParams.has_tangent = true;
vertParams.has_uv0 = true; vertParams.has_uv0 = true;
resources::Shader::ShaderSettings shaderSettings{}; Shader::ShaderSettings shaderSettings{};
shaderSettings.vertexParams = vertParams;
shaderSettings.alpha_blending = false;
shaderSettings.cull_backface = true;
shaderSettings.write_z = true;
shaderSettings.render_order = 0;
auto skyboxShader = std::make_unique<Shader>(renderer(), GetResourcePath("engine/shaders/skybox.vert").c_str(),
GetResourcePath("engine/shaders/skybox.frag").c_str(), shaderSettings);
GetResourceManager<Shader>()->AddPersistent("builtin.skybox", std::move(skyboxShader));
}
#if 0
{
Shader::VertexParams vertParams{};
vertParams.has_normal = true;
vertParams.has_tangent = true;
vertParams.has_uv0 = true;
Shader::ShaderSettings shaderSettings{};
shaderSettings.vertexParams = vertParams; shaderSettings.vertexParams = vertParams;
shaderSettings.alpha_blending = true; shaderSettings.alpha_blending = true;
shaderSettings.cull_backface = true; shaderSettings.cull_backface = true;
shaderSettings.write_z = false; shaderSettings.write_z = false;
shaderSettings.render_order = 1; shaderSettings.render_order = 1;
auto quadShader = std::make_unique<resources::Shader>(renderer(), GetResourcePath("engine/shaders/quad.vert").c_str(), auto quadShader = std::make_unique<Shader>(renderer(), GetResourcePath("engine/shaders/quad.vert").c_str(),
GetResourcePath("engine/shaders/quad.frag").c_str(), shaderSettings); GetResourcePath("engine/shaders/quad.frag").c_str(), shaderSettings);
GetResourceManager<resources::Shader>()->AddPersistent("builtin.quad", std::move(quadShader)); GetResourceManager<Shader>()->AddPersistent("builtin.quad", std::move(quadShader));
} }
#endif
/* default textures */ /* default textures */
{ {
auto whiteTexture = std::make_unique<resources::Texture>(renderer(), GetResourcePath("engine/textures/white.png"), resources::Texture::Filtering::kOff); auto whiteTexture = LoadTextureFromFile(GetResourcePath("engine/textures/white.png"), Texture::Filtering::kOff, renderer());
GetResourceManager<resources::Texture>()->AddPersistent("builtin.white", std::move(whiteTexture)); GetResourceManager<Texture>()->AddPersistent("builtin.white", std::move(whiteTexture));
} }
} }
@ -228,6 +248,7 @@ void Application::GameLoop()
return find_depth(parent, current_depth + 1); return find_depth(parent, current_depth + 1);
} }
}; };
if (scene)
{ {
for (Entity i = 1; i < scene->next_entity_id_; ++i) { for (Entity i = 1; i < scene->next_entity_id_; ++i) {
auto t = scene->GetComponent<TransformComponent>(i); auto t = scene->GetComponent<TransformComponent>(i);
@ -235,8 +256,12 @@ void Application::GameLoop()
int depth = find_depth(i, 0); int depth = find_depth(i, 0);
for (int j = 0; j < depth; ++j) tabs += std::string{" "}; for (int j = 0; j < depth; ++j) tabs += std::string{" "};
ImGui::Text("%s%s", tabs.c_str(), t->tag.c_str()); ImGui::Text("%s%s", tabs.c_str(), t->tag.c_str());
ImGui::Text("%.1f %.1f %.1f", t->position.x, t->position.y, t->position.z);
} }
} }
else {
ImGui::Text("No scene active!");
}
} }
ImGui::End(); ImGui::End();
} }
@ -253,7 +278,7 @@ void Application::GameLoop()
dynamic_list = mesh_render_system->GetDynamicRenderList(); dynamic_list = mesh_render_system->GetDynamicRenderList();
} }
renderer_->PreRender(window()->GetWindowResized(), camera_transform); renderer_->PreRender(window()->GetWindowResized(), camera_transform);
renderer_->Render(*static_list, *dynamic_list); renderer_->Render(static_list, dynamic_list);
/* poll events */ /* poll events */
window_->GetInputAndEvents(); window_->GetInputAndEvents();

View File

@ -6,9 +6,8 @@
#include "imgui/imgui.h" #include "imgui/imgui.h"
[[maybe_unused]] static glm::mat4 GenPerspectiveMatrix(float vertical_fov_radians, [[maybe_unused]] static glm::mat4 GenPerspectiveMatrix(float vertical_fov_radians, float aspect_ratio, float znear, float zfar)
float aspect_ratio, float znear, {
float zfar) {
float g = 1.0f / tanf(vertical_fov_radians * 0.5f); float g = 1.0f / tanf(vertical_fov_radians * 0.5f);
float k1 = zfar / (zfar - znear); float k1 = zfar / (zfar - znear);
float k2 = -(zfar * znear) / (znear - zfar); float k2 = -(zfar * znear) / (znear - zfar);
@ -26,10 +25,9 @@
namespace engine { namespace engine {
Renderer::Renderer(const char* app_name, const char* app_version, Renderer::Renderer(const char* app_name, const char* app_version, SDL_Window* window, gfx::GraphicsSettings settings)
SDL_Window* window, gfx::GraphicsSettings settings) { {
device_ = device_ = std::make_unique<GFXDevice>(app_name, app_version, window, settings);
std::make_unique<GFXDevice>(app_name, app_version, window, settings);
// sort out descriptor set layouts: // sort out descriptor set layouts:
std::vector<gfx::DescriptorSetLayoutBinding> globalSetBindings; std::vector<gfx::DescriptorSetLayoutBinding> globalSetBindings;
@ -41,12 +39,8 @@ Renderer::Renderer(const char* app_name, const char* app_version,
global_uniform.layout = device_->CreateDescriptorSetLayout(globalSetBindings); global_uniform.layout = device_->CreateDescriptorSetLayout(globalSetBindings);
global_uniform.set = device_->AllocateDescriptorSet(global_uniform.layout); global_uniform.set = device_->AllocateDescriptorSet(global_uniform.layout);
global_uniform.uniform_buffer_data.data = glm::mat4{1.0f}; global_uniform.uniform_buffer_data.data = glm::mat4{1.0f};
global_uniform.uniform_buffer = global_uniform.uniform_buffer = device_->CreateUniformBuffer(sizeof(global_uniform.uniform_buffer_data), &global_uniform.uniform_buffer_data);
device_->CreateUniformBuffer(sizeof(global_uniform.uniform_buffer_data), device_->UpdateDescriptorUniformBuffer(global_uniform.set, 0, global_uniform.uniform_buffer, 0, sizeof(global_uniform.uniform_buffer_data));
&global_uniform.uniform_buffer_data);
device_->UpdateDescriptorUniformBuffer(
global_uniform.set, 0, global_uniform.uniform_buffer, 0,
sizeof(global_uniform.uniform_buffer_data));
std::vector<gfx::DescriptorSetLayoutBinding> frameSetBindings; std::vector<gfx::DescriptorSetLayoutBinding> frameSetBindings;
{ {
@ -57,25 +51,24 @@ Renderer::Renderer(const char* app_name, const char* app_version,
frame_uniform.layout = device_->CreateDescriptorSetLayout(frameSetBindings); frame_uniform.layout = device_->CreateDescriptorSetLayout(frameSetBindings);
frame_uniform.set = device_->AllocateDescriptorSet(frame_uniform.layout); frame_uniform.set = device_->AllocateDescriptorSet(frame_uniform.layout);
frame_uniform.uniform_buffer_data.data = glm::mat4{1.0f}; frame_uniform.uniform_buffer_data.data = glm::mat4{1.0f};
frame_uniform.uniform_buffer = frame_uniform.uniform_buffer = device_->CreateUniformBuffer(sizeof(frame_uniform.uniform_buffer_data), &frame_uniform.uniform_buffer_data);
device_->CreateUniformBuffer(sizeof(frame_uniform.uniform_buffer_data), device_->UpdateDescriptorUniformBuffer(frame_uniform.set, 0, frame_uniform.uniform_buffer, 0, sizeof(frame_uniform.uniform_buffer_data));
&frame_uniform.uniform_buffer_data);
device_->UpdateDescriptorUniformBuffer(
frame_uniform.set, 0, frame_uniform.uniform_buffer, 0,
sizeof(frame_uniform.uniform_buffer_data));
std::vector<gfx::DescriptorSetLayoutBinding> materialSetBindings; std::vector<gfx::DescriptorSetLayoutBinding> materialSetBindings;
{ gfx::DescriptorSetLayoutBinding materialSetBinding{};
auto& binding0 = materialSetBindings.emplace_back(); materialSetBinding.descriptor_type = gfx::DescriptorType::kCombinedImageSampler;
binding0.descriptor_type = gfx::DescriptorType::kCombinedImageSampler; materialSetBinding.stage_flags = gfx::ShaderStageFlags::kFragment;
binding0.stage_flags = gfx::ShaderStageFlags::kFragment; materialSetBindings.push_back(materialSetBinding); // albedo
} materialSetBindings.push_back(materialSetBinding); // normal
materialSetBindings.push_back(materialSetBinding); // occlusion
materialSetBindings.push_back(materialSetBinding); // metallic-roughness
material_set_layout = device_->CreateDescriptorSetLayout(materialSetBindings); material_set_layout = device_->CreateDescriptorSetLayout(materialSetBindings);
device_->SetupImguiBackend(); device_->SetupImguiBackend();
}; };
Renderer::~Renderer() { Renderer::~Renderer()
{
for (const auto& [info, sampler] : samplers) { for (const auto& [info, sampler] : samplers) {
device_->DestroySampler(sampler); device_->DestroySampler(sampler);
} }
@ -88,41 +81,41 @@ Renderer::~Renderer() {
device_->DestroyDescriptorSetLayout(global_uniform.layout); device_->DestroyDescriptorSetLayout(global_uniform.layout);
} }
void Renderer::PreRender(bool window_is_resized, glm::mat4 camera_transform) { void Renderer::PreRender(bool window_is_resized, glm::mat4 camera_transform)
{
if (window_is_resized) { if (window_is_resized) {
uint32_t w, h; uint32_t w, h;
device_->GetViewportSize(&w, &h); device_->GetViewportSize(&w, &h);
viewport_aspect_ratio_ = (float)w / (float)h; viewport_aspect_ratio_ = (float)w / (float)h;
const glm::mat4 proj_matrix = glm::perspectiveRH_ZO( const glm::mat4 proj_matrix =
camera_settings_.vertical_fov_radians, viewport_aspect_ratio_, glm::perspectiveRH_ZO(camera_settings_.vertical_fov_radians, viewport_aspect_ratio_, camera_settings_.clip_near, camera_settings_.clip_far);
camera_settings_.clip_near, camera_settings_.clip_far);
/* update SET 0 (rarely changing uniforms)*/ /* update SET 0 (rarely changing uniforms)*/
global_uniform.uniform_buffer_data.data = proj_matrix; global_uniform.uniform_buffer_data.data = proj_matrix;
device_->WriteUniformBuffer(global_uniform.uniform_buffer, 0, device_->WriteUniformBuffer(global_uniform.uniform_buffer, 0, sizeof(global_uniform.uniform_buffer_data), &global_uniform.uniform_buffer_data);
sizeof(global_uniform.uniform_buffer_data),
&global_uniform.uniform_buffer_data);
} }
// set camera view matrix uniform // set camera view matrix uniform
/* update SET 1 (per frame uniforms) */ /* update SET 1 (per frame uniforms) */
const glm::mat4 view_matrix = glm::inverse(camera_transform); const glm::mat4 view_matrix = glm::inverse(camera_transform);
frame_uniform.uniform_buffer_data.data = view_matrix; frame_uniform.uniform_buffer_data.data = view_matrix;
device_->WriteUniformBuffer(frame_uniform.uniform_buffer, 0, device_->WriteUniformBuffer(frame_uniform.uniform_buffer, 0, sizeof(frame_uniform.uniform_buffer_data), &frame_uniform.uniform_buffer_data);
sizeof(frame_uniform.uniform_buffer_data),
&frame_uniform.uniform_buffer_data);
} }
void Renderer::Render(const RenderList& static_list, void Renderer::Render(const RenderList* static_list, const RenderList* dynamic_list)
const RenderList& dynamic_list) { {
last_bound_pipeline_ = nullptr; last_bound_pipeline_ = nullptr;
gfx::DrawBuffer* draw_buffer = device_->BeginRender(); gfx::DrawBuffer* draw_buffer = device_->BeginRender();
if (!static_list.empty()) { if (static_list) {
DrawRenderList(draw_buffer, static_list); if (!static_list->empty()) {
DrawRenderList(draw_buffer, *static_list);
}
}
if (dynamic_list) {
if (!dynamic_list->empty()) {
DrawRenderList(draw_buffer, *dynamic_list);
} }
if (!dynamic_list.empty()) {
DrawRenderList(draw_buffer, dynamic_list);
} }
device_->CmdRenderImguiDrawData(draw_buffer, ImGui::GetDrawData()); device_->CmdRenderImguiDrawData(draw_buffer, ImGui::GetDrawData());
@ -130,16 +123,14 @@ void Renderer::Render(const RenderList& static_list,
device_->FinishRender(draw_buffer); device_->FinishRender(draw_buffer);
} }
void Renderer::DrawRenderList(gfx::DrawBuffer* draw_buffer, void Renderer::DrawRenderList(gfx::DrawBuffer* draw_buffer, const RenderList& render_list)
const RenderList& render_list) { {
// if a pipeline hasn't been bound yet at all // if a pipeline hasn't been bound yet at all
if (last_bound_pipeline_ == nullptr) { if (last_bound_pipeline_ == nullptr) {
const gfx::Pipeline* first_pipeline = render_list.begin()->pipeline; const gfx::Pipeline* first_pipeline = render_list.begin()->pipeline;
// these bindings persist between all pipelines // these bindings persist between all pipelines
device_->CmdBindDescriptorSet(draw_buffer, first_pipeline, device_->CmdBindDescriptorSet(draw_buffer, first_pipeline, global_uniform.set, 0);
global_uniform.set, 0); device_->CmdBindDescriptorSet(draw_buffer, first_pipeline, frame_uniform.set, 1);
device_->CmdBindDescriptorSet(draw_buffer, first_pipeline,
frame_uniform.set, 1);
device_->CmdBindPipeline(draw_buffer, first_pipeline); device_->CmdBindPipeline(draw_buffer, first_pipeline);
last_bound_pipeline_ = first_pipeline; last_bound_pipeline_ = first_pipeline;
} }
@ -149,10 +140,8 @@ void Renderer::DrawRenderList(gfx::DrawBuffer* draw_buffer,
device_->CmdBindPipeline(draw_buffer, entry.pipeline); device_->CmdBindPipeline(draw_buffer, entry.pipeline);
last_bound_pipeline_ = entry.pipeline; last_bound_pipeline_ = entry.pipeline;
} }
device_->CmdBindDescriptorSet(draw_buffer, entry.pipeline, device_->CmdBindDescriptorSet(draw_buffer, entry.pipeline, entry.material_set, 2);
entry.base_colour_texture, 2); device_->CmdPushConstants(draw_buffer, entry.pipeline, 0, sizeof(entry.model_matrix), &entry.model_matrix);
device_->CmdPushConstants(draw_buffer, entry.pipeline, 0,
sizeof(entry.model_matrix), &entry.model_matrix);
device_->CmdBindVertexBuffer(draw_buffer, 0, entry.vertex_buffer); device_->CmdBindVertexBuffer(draw_buffer, 0, entry.vertex_buffer);
device_->CmdBindIndexBuffer(draw_buffer, entry.index_buffer); device_->CmdBindIndexBuffer(draw_buffer, entry.index_buffer);
device_->CmdDrawIndexed(draw_buffer, entry.index_count, 1, 0, 0, 0); device_->CmdDrawIndexed(draw_buffer, entry.index_count, 1, 0, 0, 0);

View File

@ -8,7 +8,7 @@
#include "log.h" #include "log.h"
#include "util/files.h" #include "util/files.h"
namespace engine::resources { namespace engine {
Font::Font(const std::string& path) { Font::Font(const std::string& path) {
font_buffer_ = util::ReadBinaryFile(path); font_buffer_ = util::ReadBinaryFile(path);
@ -131,4 +131,4 @@ int Font::GetGlyphIndex(int unicode_codepoint) {
} }
} }
} // namespace engine::resources } // namespace engine

View File

@ -2,18 +2,37 @@
#include "resources/shader.h" #include "resources/shader.h"
namespace engine::resources { namespace engine {
Material::Material(std::shared_ptr<Shader> shader) Material::Material(Renderer* renderer, std::shared_ptr<Shader> shader) : shader_(shader), renderer_(renderer)
: shader_(shader)
{ {
material_set_ = renderer->GetDevice()->AllocateDescriptorSet(renderer->GetMaterialSetLayout());
} }
Material::Material(const Material& original) Material::~Material() { renderer_->GetDevice()->FreeDescriptorSet(material_set_); }
: texture_(original.texture_), shader_(original.shader_)
void Material::SetAlbedoTexture(std::shared_ptr<Texture> texture)
{ {
renderer_->GetDevice()->UpdateDescriptorCombinedImageSampler(material_set_, 0, texture->GetImage(), texture->GetSampler());
texture_albedo_ = texture;
} }
void Material::SetNormalTexture(std::shared_ptr<Texture> texture)
{
renderer_->GetDevice()->UpdateDescriptorCombinedImageSampler(material_set_, 1, texture->GetImage(), texture->GetSampler());
texture_normal_ = texture;
} }
void Material::SetOcclusionTexture(std::shared_ptr<Texture> texture)
{
renderer_->GetDevice()->UpdateDescriptorCombinedImageSampler(material_set_, 2, texture->GetImage(), texture->GetSampler());
texture_occlusion_ = texture;
}
void Material::SetMetallicRoughnessTexture(std::shared_ptr<Texture> texture)
{
renderer_->GetDevice()->UpdateDescriptorCombinedImageSampler(material_set_, 3, texture->GetImage(), texture->GetSampler());
texture_metallic_roughness_ = texture;
}
} // namespace engine

View File

@ -3,7 +3,7 @@
#include "log.h" #include "log.h"
#include "gfx_device.h" #include "gfx_device.h"
namespace engine::resources { namespace engine {
Mesh::Mesh(GFXDevice* gfx, const std::vector<Vertex>& vertices) : gfx_(gfx) { Mesh::Mesh(GFXDevice* gfx, const std::vector<Vertex>& vertices) : gfx_(gfx) {
std::vector<uint32_t> indices(vertices.size()); std::vector<uint32_t> indices(vertices.size());
@ -36,4 +36,4 @@ void Mesh::InitMesh(const std::vector<Vertex>& vertices,
indices.size()); indices.size());
} }
} // namespace engine::resources } // namespace engine

View File

@ -6,7 +6,7 @@
#include <glm/mat4x4.hpp> #include <glm/mat4x4.hpp>
namespace engine::resources { namespace engine {
Shader::Shader(Renderer* renderer, const char* vertPath, const char* fragPath, Shader::Shader(Renderer* renderer, const char* vertPath, const char* fragPath,
const ShaderSettings& settings) const ShaderSettings& settings)
@ -67,4 +67,4 @@ Shader::~Shader() {
const gfx::Pipeline* Shader::GetPipeline() { return pipeline_; } const gfx::Pipeline* Shader::GetPipeline() { return pipeline_; }
} // namespace engine::resources } // namespace engine

View File

@ -6,15 +6,10 @@
#include <vector> #include <vector>
namespace engine::resources { namespace engine {
Texture::Texture(Renderer* renderer, const std::string& path,
Filtering filtering)
: gfx_(renderer->GetDevice()) {
int width, height;
std::unique_ptr<std::vector<uint8_t>> texbuf =
util::ReadImageFile(path, &width, &height);
Texture::Texture(Renderer* renderer, const uint8_t* bitmap, int width, int height, Filtering filtering) : gfx_(renderer->GetDevice())
{
gfx::SamplerInfo samplerInfo{}; gfx::SamplerInfo samplerInfo{};
samplerInfo.magnify = gfx::Filter::kLinear; samplerInfo.magnify = gfx::Filter::kLinear;
@ -42,66 +37,26 @@ Texture::Texture(Renderer* renderer, const std::string& path,
} }
if (renderer->samplers.contains(samplerInfo) == false) { if (renderer->samplers.contains(samplerInfo) == false) {
renderer->samplers.insert( renderer->samplers.insert(std::make_pair(samplerInfo, gfx_->CreateSampler(samplerInfo)));
std::make_pair(samplerInfo, gfx_->CreateSampler(samplerInfo)));
}
image_ = gfx_->CreateImage(width, height, texbuf->data());
descriptor_set_ =
gfx_->AllocateDescriptorSet(renderer->GetMaterialSetLayout());
gfx_->UpdateDescriptorCombinedImageSampler(
descriptor_set_, 0, image_, renderer->samplers.at(samplerInfo));
LOG_DEBUG("Created texture: {}, width: {} height: {}", path, width, height);
}
Texture::Texture(Renderer* renderer, const uint8_t* bitmap, int width,
int height, Filtering filtering)
: gfx_(renderer->GetDevice()) {
gfx::SamplerInfo samplerInfo{};
samplerInfo.magnify = gfx::Filter::kLinear;
switch (filtering) {
case Filtering::kOff:
samplerInfo.minify = gfx::Filter::kNearest;
samplerInfo.mipmap = gfx::Filter::kNearest;
samplerInfo.anisotropic_filtering = false;
break;
case Filtering::kBilinear:
samplerInfo.minify = gfx::Filter::kLinear;
samplerInfo.mipmap = gfx::Filter::kNearest;
samplerInfo.anisotropic_filtering = false;
break;
case Filtering::kTrilinear:
samplerInfo.minify = gfx::Filter::kLinear;
samplerInfo.mipmap = gfx::Filter::kLinear;
samplerInfo.anisotropic_filtering = false;
break;
case Filtering::kAnisotropic:
samplerInfo.minify = gfx::Filter::kLinear;
samplerInfo.mipmap = gfx::Filter::kLinear;
samplerInfo.anisotropic_filtering = true;
}
if (renderer->samplers.contains(samplerInfo) == false) {
renderer->samplers.insert(
std::make_pair(samplerInfo, gfx_->CreateSampler(samplerInfo)));
} }
image_ = gfx_->CreateImage(width, height, bitmap); image_ = gfx_->CreateImage(width, height, bitmap);
descriptor_set_ = sampler_ = renderer->samplers.at(samplerInfo);
gfx_->AllocateDescriptorSet(renderer->GetMaterialSetLayout());
gfx_->UpdateDescriptorCombinedImageSampler(
descriptor_set_, 0, image_, renderer->samplers.at(samplerInfo));
LOG_DEBUG("Created texture: BITMAP, width: {} height: {}", width, height); LOG_DEBUG("Created texture: width: {}, height: {}", width, height);
} }
Texture::~Texture() { Texture::~Texture()
{
LOG_DEBUG("Destroying texture..."); LOG_DEBUG("Destroying texture...");
gfx_->FreeDescriptorSet(descriptor_set_);
gfx_->DestroyImage(image_); gfx_->DestroyImage(image_);
} }
} // namespace engine::resources std::unique_ptr<Texture> LoadTextureFromFile(const std::string& path, Texture::Filtering filtering, Renderer* renderer)
{
int width, height;
auto bitmap = util::ReadImageFile(path, width, height);
return std::make_unique<Texture>(renderer, bitmap->data(), width, height, filtering);
}
} // namespace engine

View File

@ -7,10 +7,7 @@
namespace engine { namespace engine {
SceneManager::SceneManager(Application* app) SceneManager::SceneManager(Application* app) : app_(app) {}
: app_(app)
{
}
SceneManager::~SceneManager() {} SceneManager::~SceneManager() {}
@ -18,7 +15,6 @@ namespace engine {
{ {
auto scene = std::make_unique<Scene>(app_); auto scene = std::make_unique<Scene>(app_);
scenes_.emplace_back(std::move(scene)); scenes_.emplace_back(std::move(scene));
active_scene_index_ = (int)scenes_.size() - 1;
return scenes_.back().get(); return scenes_.back().get();
} }
@ -29,9 +25,10 @@ namespace engine {
Scene* activeScene = scenes_[active_scene_index_].get(); Scene* activeScene = scenes_[active_scene_index_].get();
activeScene->Update(ts); activeScene->Update(ts);
return activeScene; return activeScene;
} else { }
else {
return nullptr; return nullptr;
} }
} }
} } // namespace engine

View File

@ -8,23 +8,24 @@
namespace engine { namespace engine {
MeshRenderSystem::MeshRenderSystem(Scene* scene) MeshRenderSystem::MeshRenderSystem(Scene* scene) : System(scene, {typeid(TransformComponent).hash_code(), typeid(MeshRenderableComponent).hash_code()}) {}
: System(scene, {typeid(TransformComponent).hash_code(),
typeid(MeshRenderableComponent).hash_code()}) {}
MeshRenderSystem::~MeshRenderSystem() {} MeshRenderSystem::~MeshRenderSystem() {}
void MeshRenderSystem::RebuildStaticRenderList() { void MeshRenderSystem::RebuildStaticRenderList()
{
BuildRenderList(static_render_list_, true); BuildRenderList(static_render_list_, true);
list_needs_rebuild_ = false; list_needs_rebuild_ = false;
} }
void MeshRenderSystem::OnComponentInsert(Entity entity) { void MeshRenderSystem::OnComponentInsert(Entity entity)
{
(void)entity; (void)entity;
list_needs_rebuild_ = true; list_needs_rebuild_ = true;
} }
void MeshRenderSystem::OnUpdate(float ts) { void MeshRenderSystem::OnUpdate(float ts)
{
// do stuff // do stuff
(void)ts; (void)ts;
// update the static render list only if it needs updating // update the static render list only if it needs updating
@ -35,8 +36,8 @@ void MeshRenderSystem::OnUpdate(float ts) {
BuildRenderList(dynamic_render_list_, false); BuildRenderList(dynamic_render_list_, false);
} }
void MeshRenderSystem::BuildRenderList(RenderList& render_list, void MeshRenderSystem::BuildRenderList(RenderList& render_list, bool with_static_entities)
bool with_static_entities) { {
render_list.clear(); render_list.clear();
render_list.reserve(entities_.size()); render_list.reserve(entities_.size());
@ -49,27 +50,22 @@ void MeshRenderSystem::BuildRenderList(RenderList& render_list,
auto renderable = scene_->GetComponent<engine::MeshRenderableComponent>(entity); auto renderable = scene_->GetComponent<engine::MeshRenderableComponent>(entity);
const gfx::Pipeline* pipeline = const gfx::Pipeline* pipeline = renderable->material->GetShader()->GetPipeline();
renderable->material->GetShader()->GetPipeline();
render_list.emplace_back( render_list.emplace_back(RenderListEntry{.pipeline = pipeline,
RenderListEntry{.pipeline = pipeline,
.vertex_buffer = renderable->mesh->GetVB(), .vertex_buffer = renderable->mesh->GetVB(),
.index_buffer = renderable->mesh->GetIB(), .index_buffer = renderable->mesh->GetIB(),
.base_colour_texture = .material_set = renderable->material->GetDescriptorSet(),
renderable->material->texture_->GetDescriptorSet(),
.model_matrix = transform->world_matrix, .model_matrix = transform->world_matrix,
.index_count = renderable->mesh->GetCount()}); .index_count = renderable->mesh->GetCount()});
if (render_orders.contains(pipeline) == false) { if (render_orders.contains(pipeline) == false) {
render_orders.emplace( render_orders.emplace(pipeline, renderable->material->GetShader()->GetRenderOrder());
pipeline, renderable->material->GetShader()->GetRenderOrder());
} }
} }
// sort the meshes by pipeline // sort the meshes by pipeline
auto sort_by_pipeline = [&render_orders](const RenderListEntry& e1, auto sort_by_pipeline = [&render_orders](const RenderListEntry& e1, const RenderListEntry& e2) -> bool {
const RenderListEntry& e2) -> bool {
return (render_orders.at(e1.pipeline) < render_orders.at(e2.pipeline)); return (render_orders.at(e1.pipeline) < render_orders.at(e2.pipeline));
}; };

View File

@ -54,7 +54,7 @@ std::unique_ptr<std::vector<uint8_t>> ReadBinaryFile(const std::string& path) {
} }
std::unique_ptr<std::vector<uint8_t>> ReadImageFile(const std::string& path, std::unique_ptr<std::vector<uint8_t>> ReadImageFile(const std::string& path,
int* width, int* height) { int& width, int& height) {
int x, y, n; int x, y, n;
unsigned char* data = unsigned char* data =
stbi_load(path.c_str(), &x, &y, &n, STBI_rgb_alpha); // Image is 4 bpp stbi_load(path.c_str(), &x, &y, &n, STBI_rgb_alpha); // Image is 4 bpp
@ -68,8 +68,8 @@ std::unique_ptr<std::vector<uint8_t>> ReadImageFile(const std::string& path,
auto buffer = std::make_unique<std::vector<uint8_t>>(size); auto buffer = std::make_unique<std::vector<uint8_t>>(size);
memcpy(buffer->data(), data, buffer->size()); memcpy(buffer->data(), data, buffer->size());
*width = x; width = x;
*height = y; height = y;
stbi_image_free(data); stbi_image_free(data);

View File

@ -27,11 +27,8 @@
namespace engine::util { namespace engine::util {
static void buildGraph( static void buildGraph(const std::map<int, std::shared_ptr<Texture>>& textures, const std::vector<std::shared_ptr<Mesh>>& meshes,
const std::map<int, std::shared_ptr<resources::Texture>>& textures, const std::vector<unsigned int>& meshTextureIndices, aiNode* parentNode, Scene* scene, Entity parentObj, bool is_static)
const std::vector<std::shared_ptr<resources::Mesh>>& meshes,
const std::vector<unsigned int>& meshTextureIndices,
aiNode* parentNode, Scene* scene, Entity parentObj, bool is_static)
{ {
// convert to glm column major // convert to glm column major
@ -86,23 +83,18 @@ namespace engine::util {
scene->GetComponent<TransformComponent>(child)->is_static = is_static; scene->GetComponent<TransformComponent>(child)->is_static = is_static;
auto childRenderer = scene->AddComponent<MeshRenderableComponent>(child); auto childRenderer = scene->AddComponent<MeshRenderableComponent>(child);
childRenderer->mesh = meshes[parentNode->mMeshes[i]]; childRenderer->mesh = meshes[parentNode->mMeshes[i]];
childRenderer->material = std::make_shared<resources::Material>(scene->app()->GetResource<resources::Shader>("builtin.standard")); childRenderer->material = std::make_shared<Material>(scene->app()->renderer(), scene->app()->GetResource<Shader>("builtin.standard"));
if (textures.contains(meshTextureIndices[parentNode->mMeshes[i]])) { if (textures.contains(meshTextureIndices[parentNode->mMeshes[i]])) {
childRenderer->material->texture_ = textures.at(meshTextureIndices[parentNode->mMeshes[i]]); childRenderer->material->SetAlbedoTexture(textures.at(meshTextureIndices[parentNode->mMeshes[i]]));
} else { }
childRenderer->material->texture_ = scene->app()->GetResource<resources::Texture>("builtin.white"); else {
childRenderer->material->SetAlbedoTexture(scene->app()->GetResource<Texture>("builtin.white"));
} }
} }
for (uint32_t i = 0; i < parentNode->mNumChildren; i++) { for (uint32_t i = 0; i < parentNode->mNumChildren; i++) {
buildGraph( buildGraph(textures, meshes, meshTextureIndices, parentNode->mChildren[i], scene, scene->CreateEntity("child" + std::to_string(i), parentObj),
textures, is_static);
meshes,
meshTextureIndices,
parentNode->mChildren[i],
scene,
scene->CreateEntity("child" + std::to_string(i), parentObj), is_static
);
} }
} }
@ -113,7 +105,8 @@ namespace engine::util {
class myStream : public Assimp::LogStream { class myStream : public Assimp::LogStream {
public: public:
void write(const char* message) override { void write(const char* message) override
{
(void)message; (void)message;
LOG_TRACE("ASSIMP: {}", message); LOG_TRACE("ASSIMP: {}", message);
} }
@ -123,38 +116,18 @@ namespace engine::util {
Assimp::DefaultLogger::get()->attachStream(new myStream, severity); Assimp::DefaultLogger::get()->attachStream(new myStream, severity);
// remove everything but texcoords, normals, meshes, materials // remove everything but texcoords, normals, meshes, materials
importer.SetPropertyInteger(AI_CONFIG_PP_RVC_FLAGS, importer.SetPropertyInteger(AI_CONFIG_PP_RVC_FLAGS, aiComponent_ANIMATIONS | aiComponent_BONEWEIGHTS | aiComponent_CAMERAS | aiComponent_COLORS |
aiComponent_ANIMATIONS | aiComponent_LIGHTS | aiComponent_TANGENTS_AND_BITANGENTS | aiComponent_TEXTURES | 0);
aiComponent_BONEWEIGHTS | importer.SetPropertyInteger(AI_CONFIG_PP_SBP_REMOVE, aiPrimitiveType_POINT | aiPrimitiveType_LINE | aiPrimitiveType_POLYGON);
aiComponent_CAMERAS |
aiComponent_COLORS |
aiComponent_LIGHTS |
aiComponent_TANGENTS_AND_BITANGENTS |
aiComponent_TEXTURES |
0
);
importer.SetPropertyInteger(AI_CONFIG_PP_SBP_REMOVE,
aiPrimitiveType_POINT |
aiPrimitiveType_LINE |
aiPrimitiveType_POLYGON
);
const aiScene* scene = importer.ReadFile(path, const aiScene* scene =
aiProcess_JoinIdenticalVertices | importer.ReadFile(path,
aiProcess_Triangulate | aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType | aiProcess_RemoveComponent |
aiProcess_SortByPType |
aiProcess_RemoveComponent |
aiProcess_SplitLargeMeshes | // leave at default maximum aiProcess_SplitLargeMeshes | // leave at default maximum
aiProcess_ValidateDataStructure | // make sure to log the output aiProcess_ValidateDataStructure | // make sure to log the output
aiProcess_ImproveCacheLocality | aiProcess_ImproveCacheLocality | aiProcess_RemoveRedundantMaterials | aiProcess_FindInvalidData | aiProcess_GenSmoothNormals |
aiProcess_RemoveRedundantMaterials | aiProcess_GenUVCoords | aiProcess_TransformUVCoords | aiProcess_FlipUVs | // Collada uses bottom-left origin
aiProcess_FindInvalidData | aiProcess_CalcTangentSpace | 0);
aiProcess_GenSmoothNormals |
aiProcess_GenUVCoords |
aiProcess_TransformUVCoords |
aiProcess_FlipUVs | // Collada uses bottom-left origin
0
);
const char* errString = importer.GetErrorString(); const char* errString = importer.GetErrorString();
if (errString[0] != '\0' || scene == nullptr) { if (errString[0] != '\0' || scene == nullptr) {
@ -172,7 +145,7 @@ namespace engine::util {
LOG_TRACE("material count: {}, mesh count: {}", scene->mNumMaterials, scene->mNumMeshes); LOG_TRACE("material count: {}, mesh count: {}", scene->mNumMaterials, scene->mNumMeshes);
std::map<int, std::shared_ptr<resources::Texture>> textures{}; std::map<int, std::shared_ptr<Texture>> textures{};
for (uint32_t i = 0; i < scene->mNumMaterials; i++) { for (uint32_t i = 0; i < scene->mNumMaterials; i++) {
const aiMaterial* m = scene->mMaterials[i]; const aiMaterial* m = scene->mMaterials[i];
@ -191,17 +164,15 @@ namespace engine::util {
absPath = absPath.parent_path(); absPath = absPath.parent_path();
absPath /= texPath.C_Str(); absPath /= texPath.C_Str();
try { try {
textures[i] = std::make_shared<resources::Texture>( textures[i] = LoadTextureFromFile(absPath.string(), Texture::Filtering::kTrilinear, parent->app()->renderer());
parent->app()->renderer(), }
absPath.string(), catch (const std::runtime_error&) {
resources::Texture::Filtering::kTrilinear); textures[i] = parent->app()->GetResource<Texture>("builtin.white");
} catch (const std::runtime_error&) {
textures[i] = parent->app()->GetResource<resources::Texture>("builtin.white");
} }
} }
} }
std::vector<std::shared_ptr<resources::Mesh>> meshes{}; std::vector<std::shared_ptr<Mesh>> meshes{};
std::vector<unsigned int> meshMaterialIndices{}; std::vector<unsigned int> meshMaterialIndices{};
for (uint32_t i = 0; i < scene->mNumMeshes; i++) { for (uint32_t i = 0; i < scene->mNumMeshes; i++) {
const aiMesh* m = scene->mMeshes[i]; const aiMesh* m = scene->mMeshes[i];
@ -211,6 +182,10 @@ namespace engine::util {
LOG_TRACE("Mesh {}: vertex count {}", i, vertices.size()); LOG_TRACE("Mesh {}: vertex count {}", i, vertices.size());
LOG_TRACE("Mesh {}: index count {}", i, indices.size()); LOG_TRACE("Mesh {}: index count {}", i, indices.size());
if (m->mTangents == nullptr) {
throw std::runtime_error("No tangents array found!");
}
for (uint32_t j = 0; j < vertices.size(); j++) { for (uint32_t j = 0; j < vertices.size(); j++) {
Vertex v{}; Vertex v{};
v.pos.x = m->mVertices[j].x; v.pos.x = m->mVertices[j].x;
@ -219,24 +194,21 @@ namespace engine::util {
v.norm.x = m->mNormals[j].x; v.norm.x = m->mNormals[j].x;
v.norm.y = m->mNormals[j].y; v.norm.y = m->mNormals[j].y;
v.norm.z = m->mNormals[j].z; v.norm.z = m->mNormals[j].z;
v.tangent.x = m->mTangents[j].x;
v.tangent.y = m->mTangents[j].y;
v.tangent.z = m->mTangents[j].z;
v.tangent.w = 1.0f;
v.uv.x = m->mTextureCoords[0][j].x;
v.uv.y = m->mTextureCoords[0][j].y;
vertices[j] = v; vertices[j] = v;
} }
if (m->mNumUVComponents[0] >= 2) {
for (uint32_t j = 0; j < vertices.size(); j++) {
vertices[j].uv.x = m->mTextureCoords[0][j].x;
vertices[j].uv.y = m->mTextureCoords[0][j].y;
}
}
for (uint32_t j = 0; j < indices.size() / 3; j++) { for (uint32_t j = 0; j < indices.size() / 3; j++) {
indices[(size_t)j * 3 + 0] = m->mFaces[j].mIndices[0]; indices[(size_t)j * 3 + 0] = m->mFaces[j].mIndices[0];
indices[(size_t)j * 3 + 1] = m->mFaces[j].mIndices[1]; indices[(size_t)j * 3 + 1] = m->mFaces[j].mIndices[1];
indices[(size_t)j * 3 + 2] = m->mFaces[j].mIndices[2]; indices[(size_t)j * 3 + 2] = m->mFaces[j].mIndices[2];
} }
meshes.push_back(std::make_shared<resources::Mesh>( meshes.push_back(std::make_shared<Mesh>(parent->app()->renderer()->GetDevice(), vertices, indices));
parent->app()->renderer()->GetDevice(), vertices,
indices));
} }
Entity obj = parent->CreateEntity(scene->GetShortFilename(path.c_str())); Entity obj = parent->CreateEntity(scene->GetShortFilename(path.c_str()));
@ -249,4 +221,4 @@ namespace engine::util {
return obj; return obj;
} }
} } // namespace engine::util

View File

@ -167,8 +167,8 @@ namespace engine {
{ {
const ImGuiIO& io = ImGui::GetIO(); const ImGuiIO& io = ImGui::GetIO();
if (io.WantCaptureMouse) { if (io.WantCaptureMouse) {
mouse_.dx = 0.0f; mouse_.dx = 0;
mouse_.dy = 0.0f; mouse_.dy = 0;
} }
else { else {
mouse_.x = e.x; mouse_.x = e.x;

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 194 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 559 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 186 KiB

View File

@ -105,6 +105,7 @@ void CameraControllerSystem::OnUpdate(float ts) {
} }
if (scene_->app()->input_manager()->GetButtonPress("exit")) { if (scene_->app()->input_manager()->GetButtonPress("exit")) {
scene_->app()->window()->SetCloseFlag(); //scene_->app()->window()->SetCloseFlag();
scene_->app()->scene_manager()->SetActiveScene(next_scene_);
} }
} }

View File

@ -23,6 +23,8 @@ class CameraControllerSystem
engine::TransformComponent* t = nullptr; engine::TransformComponent* t = nullptr;
CameraControllerComponent* c = nullptr; CameraControllerComponent* c = nullptr;
engine::Scene* next_scene_ = nullptr;
}; };
#endif #endif

View File

@ -56,12 +56,11 @@ void PlayGame(GameSettings settings)
app.window()->SetRelativeMouseMode(true); app.window()->SetRelativeMouseMode(true);
ConfigureInputs(app.input_manager()); ConfigureInputs(app.input_manager());
engine::Scene* my_scene = app.scene_manager()->CreateEmptyScene();
{ {
static auto my_scene = app.scene_manager()->CreateEmptyScene();
/* create camera */ { /* create camera */
{ engine::Entity camera = my_scene->CreateEntity("camera");
auto camera = my_scene->CreateEntity("camera");
/* as of right now, the entity with tag 'camera' is used to build the view /* as of right now, the entity with tag 'camera' is used to build the view
* matrix */ * matrix */
@ -74,19 +73,23 @@ void PlayGame(GameSettings settings)
my_scene->AddComponent<CameraControllerComponent>(camera); my_scene->AddComponent<CameraControllerComponent>(camera);
} }
/* shared resources */ { /* floor */
auto grass_texture = std::make_shared<engine::resources::Texture>(app.renderer(), app.GetResourcePath("textures/grass.png"), engine::Entity floor = engine::util::LoadMeshFromFile(my_scene, app.GetResourcePath("models/terrain.dae"), true);
engine::resources::Texture::Filtering::kAnisotropic); }
auto sky_texture = std::make_shared<engine::resources::Texture>(app.renderer(), app.GetResourcePath("textures/sky.jpg"), #if 0
engine::resources::Texture::Filtering::kAnisotropic);
/* shared resources */
auto grass_texture = engine::LoadTextureFromFile(app.GetResourcePath("textures/grass.png"), engine::Texture::Filtering::kAnisotropic, app.renderer());
std::shared_ptr<engine::Texture> sky_texture = engine::LoadTextureFromFile(app.GetResourcePath("textures/sky.jpg"), engine::Texture::Filtering::kAnisotropic, app.renderer());
/* skybox */ /* skybox */
{ {
engine::Entity skybox = my_scene->CreateEntity("skybox"); engine::Entity skybox = my_scene->CreateEntity("skybox");
auto skybox_renderable = my_scene->AddComponent<engine::MeshRenderableComponent>(skybox); auto skybox_renderable = my_scene->AddComponent<engine::MeshRenderableComponent>(skybox);
skybox_renderable->material = std::make_unique<engine::resources::Material>(app.GetResource<engine::resources::Shader>("builtin.skybox")); skybox_renderable->material = std::make_unique<engine::Material>(app.GetResource<engine::Shader>("builtin.skybox"));
skybox_renderable->material->texture_ = sky_texture; skybox_renderable->material->texture_ = sky_texture;
skybox_renderable->mesh = GenCuboidMesh(app.renderer()->GetDevice(), 10.0f, 10.0f, 10.0f, 1.0f, true); skybox_renderable->mesh = GenCuboidMesh(app.renderer()->GetDevice(), 10.0f, 10.0f, 10.0f, 1.0f, true);
@ -95,14 +98,6 @@ void PlayGame(GameSettings settings)
skybox_transform->position = {-5.0f, -5.0f, -5.0f}; skybox_transform->position = {-5.0f, -5.0f, -5.0f};
} }
/* floor */
{
engine::Entity floor = engine::util::LoadMeshFromFile(my_scene, app.GetResourcePath("models/terrain.dae"), true);
auto floor_transform = my_scene->GetComponent<engine::TransformComponent>(floor);
floor_transform->is_static = true;
}
/* building */ /* building */
{ {
auto cobbleHouse = engine::util::LoadMeshFromFile(my_scene, app.GetResourcePath("models/cobble_house/cobble_house.dae"), false); auto cobbleHouse = engine::util::LoadMeshFromFile(my_scene, app.GetResourcePath("models/cobble_house/cobble_house.dae"), false);
@ -119,9 +114,9 @@ void PlayGame(GameSettings settings)
engine::Entity cube = my_scene->CreateEntity("cube", 0, glm::vec3{40.0f, 10.0f, 5.0f}); engine::Entity cube = my_scene->CreateEntity("cube", 0, glm::vec3{40.0f, 10.0f, 5.0f});
auto cubeRenderable = my_scene->AddComponent<engine::MeshRenderableComponent>(cube); auto cubeRenderable = my_scene->AddComponent<engine::MeshRenderableComponent>(cube);
cubeRenderable->mesh = GenCuboidMesh(app.renderer()->GetDevice(), 1.0f, 1.0f, 1.0f); cubeRenderable->mesh = GenCuboidMesh(app.renderer()->GetDevice(), 1.0f, 1.0f, 1.0f);
cubeRenderable->material = std::make_unique<engine::resources::Material>(app.GetResource<engine::resources::Shader>("builtin.standard")); cubeRenderable->material = std::make_unique<engine::Material>(app.GetResource<engine::Shader>("builtin.standard"));
cubeRenderable->material->texture_ = std::make_unique<engine::resources::Texture>(app.renderer(), app.GetResourcePath("textures/uvcheck.png"), cubeRenderable->material->texture_ =
engine::resources::Texture::Filtering::kAnisotropic); engine::LoadTextureFromFile(app.GetResourcePath("textures/uvcheck.png"), engine::Texture::Filtering::kAnisotropic, app.renderer());
} }
/* some text */ /* some text */
@ -149,6 +144,59 @@ void PlayGame(GameSettings settings)
// engine::util::LoadGLTF(*my_scene, app.GetResourcePath("engine/models/test/test.gltf")); // engine::util::LoadGLTF(*my_scene, app.GetResourcePath("engine/models/test/test.gltf"));
#endif
}
engine::Scene* scene2 = app.scene_manager()->CreateEmptyScene();
{
{ /* create camera */
engine::Entity camera = scene2->CreateEntity("camera");
/* as of right now, the entity with tag 'camera' is used to build the view
* matrix */
auto camera_transform = scene2->GetComponent<engine::TransformComponent>(camera);
camera_transform->position = {0.0f, 0.0f, 10.0f};
scene2->RegisterComponent<CameraControllerComponent>();
scene2->RegisterSystem<CameraControllerSystem>();
scene2->AddComponent<CameraControllerComponent>(camera);
}
{ /* house */
engine::Entity floor = engine::util::LoadMeshFromFile(scene2, app.GetResourcePath("models/cobble_house/cobble_house.dae"), true);
}
{ /* axes */
engine::util::LoadMeshFromFile(scene2, app.GetResourcePath("models/MY_AXES.dae"), true);
}
{ /* a wall */
engine::Entity wall = scene2->CreateEntity("wall", 0, glm::vec3{50.0f, 0.0f, 0.0f});
auto wall_renderable = scene2->AddComponent<engine::MeshRenderableComponent>(wall);
wall_renderable->mesh = GenCuboidMesh(app.renderer()->GetDevice(), 8.0f, 8.0f, 8.0f);
wall_renderable->material = std::make_unique<engine::Material>(app.renderer(), app.GetResource<engine::Shader>("builtin.fancy"));
std::shared_ptr<engine::Texture> albedo_texture =
engine::LoadTextureFromFile(app.GetResourcePath("textures/brickwall_albedo.jpg"), engine::Texture::Filtering::kTrilinear, app.renderer());
std::shared_ptr<engine::Texture> normal_texture =
engine::LoadTextureFromFile(app.GetResourcePath("textures/testnormal.png"), engine::Texture::Filtering::kTrilinear, app.renderer());
wall_renderable->material->SetAlbedoTexture(app.GetResource<engine::Texture>("builtin.white"));
wall_renderable->material->SetNormalTexture(normal_texture);
auto custom = scene2->AddComponent<engine::CustomComponent>(wall);
custom->onInit = []() {};
custom->onUpdate = [&](float dt) {
//scene2->GetComponent<engine::TransformComponent>(wall)->rotation *= glm::angleAxis(dt, glm::normalize(glm::vec3{2.0f, 1.0f, 1.0f}));
};
}
}
my_scene->GetSystem<CameraControllerSystem>()->next_scene_ = scene2;
scene2->GetSystem<CameraControllerSystem>()->next_scene_ = my_scene;
app.scene_manager()->SetActiveScene(my_scene);
app.GameLoop(); app.GameLoop();
} }
}

View File

@ -8,7 +8,7 @@
#include "resources/mesh.h" #include "resources/mesh.h"
std::unique_ptr<engine::resources::Mesh> GenSphereMesh(engine::GFXDevice* gfx, float r, int detail, bool wind_inside, bool flip_normals) std::unique_ptr<engine::Mesh> GenSphereMesh(engine::GFXDevice* gfx, float r, int detail, bool wind_inside, bool flip_normals)
{ {
using namespace glm; using namespace glm;
@ -34,26 +34,26 @@ std::unique_ptr<engine::resources::Mesh> GenSphereMesh(engine::GFXDevice* gfx, f
// tris are visible from outside the sphere // tris are visible from outside the sphere
// triangle 1 // triangle 1
vertices.push_back({top_left, {}, {0.0f, 0.0f}}); vertices.push_back({top_left, {}, {}, {0.0f, 0.0f}});
vertices.push_back({bottom_left, {}, {0.0f, 1.0f}}); vertices.push_back({bottom_left, {}, {}, {0.0f, 1.0f}});
vertices.push_back({bottom_right, {}, {1.0f, 1.0f}}); vertices.push_back({bottom_right, {}, {}, {1.0f, 1.0f}});
// triangle 2 // triangle 2
vertices.push_back({top_right, {}, {1.0f, 0.0f}}); vertices.push_back({top_right, {}, {}, {1.0f, 0.0f}});
vertices.push_back({top_left, {}, {0.0f, 0.0f}}); vertices.push_back({top_left, {}, {}, {0.0f, 0.0f}});
vertices.push_back({bottom_right, {}, {1.0f, 1.0f}}); vertices.push_back({bottom_right, {}, {}, {1.0f, 1.0f}});
} }
else { else {
// tris are visible from inside the sphere // tris are visible from inside the sphere
// triangle 1 // triangle 1
vertices.push_back({bottom_right, {}, {1.0f, 1.0f}}); vertices.push_back({bottom_right, {}, {}, {1.0f, 1.0f}});
vertices.push_back({bottom_left, {}, {0.0f, 1.0f}}); vertices.push_back({bottom_left, {}, {}, {0.0f, 1.0f}});
vertices.push_back({top_left, {}, {0.0f, 0.0f}}); vertices.push_back({top_left, {}, {}, {0.0f, 0.0f}});
// triangle 2 // triangle 2
vertices.push_back({bottom_right, {}, {1.0f, 1.0f}}); vertices.push_back({bottom_right, {}, {}, {1.0f, 1.0f}});
vertices.push_back({top_left, {}, {0.0f, 0.0f}}); vertices.push_back({top_left, {}, {}, {0.0f, 0.0f}});
vertices.push_back({top_right, {}, {1.0f, 0.0f}}); vertices.push_back({top_right, {}, {}, {1.0f, 0.0f}});
} }
vec3 vector1 = (vertices.end() - 1)->pos - (vertices.end() - 2)->pos; vec3 vector1 = (vertices.end() - 1)->pos - (vertices.end() - 2)->pos;
@ -72,10 +72,10 @@ std::unique_ptr<engine::resources::Mesh> GenSphereMesh(engine::GFXDevice* gfx, f
} }
} }
return std::make_unique<engine::resources::Mesh>(gfx, vertices); return std::make_unique<engine::Mesh>(gfx, vertices);
} }
std::unique_ptr<engine::resources::Mesh> GenCuboidMesh(engine::GFXDevice* gfx, float x, float y, float z, float tiling, bool wind_inside) std::unique_ptr<engine::Mesh> GenCuboidMesh(engine::GFXDevice* gfx, float x, float y, float z, float tiling, bool wind_inside)
{ {
// x goes -> // x goes ->
// y goes ^ // y goes ^
@ -86,47 +86,47 @@ std::unique_ptr<engine::resources::Mesh> GenCuboidMesh(engine::GFXDevice* gfx, f
std::vector<engine::Vertex> v{}; std::vector<engine::Vertex> v{};
// front // front
v.push_back({ {0.0f, 0.0f, z}, {0.0f, -1.0f, 0.0f}, {0.0f, 0.0f} }); v.push_back({{0.0f, 0.0f, z}, {0.0f, -1.0f, 0.0f}, {1.0f, 0.0f, 0.0f, 1.0f}, {0.0f, 0.0f}});
v.push_back({ {0.0f, 0.0f, 0.0f}, {0.0f, -1.0f, 0.0f}, {0.0f, tiling} }); v.push_back({{0.0f, 0.0f, 0.0f}, {0.0f, -1.0f, 0.0f}, {1.0f, 0.0f, 0.0f, 1.0f}, {0.0f, tiling}});
v.push_back({ {x, 0.0f, 0.0f}, {0.0f, -1.0f, 0.0f}, {tiling, tiling} }); v.push_back({{x, 0.0f, 0.0f}, {0.0f, -1.0f, 0.0f}, {1.0f, 0.0f, 0.0f, 1.0f}, {tiling, tiling}});
v.push_back({ {x, 0.0f, 0.0f}, {0.0f, -1.0f, 0.0f}, {tiling, tiling} }); v.push_back({{x, 0.0f, 0.0f}, {0.0f, -1.0f, 0.0f}, {1.0f, 0.0f, 0.0f, 1.0f}, {tiling, tiling}});
v.push_back({ {x, 0.0f, z}, {0.0f, -1.0f, 0.0f}, {tiling, 0.0f} }); v.push_back({{x, 0.0f, z}, {0.0f, -1.0f, 0.0f}, {1.0f, 0.0f, 0.0f, 1.0f}, {tiling, 0.0f}});
v.push_back({ {0.0f, 0.0f, z}, {0.0f, -1.0f, 0.0f}, {0.0f, 0.0f} }); v.push_back({{0.0f, 0.0f, z}, {0.0f, -1.0f, 0.0f}, {1.0f, 0.0f, 0.0f, 1.0f}, {0.0f, 0.0f}});
// back // back
v.push_back({ {x, y, z}, {0.0f, 1.0f, 0.0f}, {0.0f, 0.0f} }); v.push_back({{x, y, z}, {0.0f, 1.0f, 0.0f}, {}, {0.0f, 0.0f}});
v.push_back({ {x, y, 0.0f}, {0.0f, 1.0f, 0.0f}, {0.0f, tiling} }); v.push_back({{x, y, 0.0f}, {0.0f, 1.0f, 0.0f}, {}, {0.0f, tiling}});
v.push_back({ {0.0f, y, 0.0f}, {0.0f, 1.0f, 0.0f}, {tiling, tiling} }); v.push_back({{0.0f, y, 0.0f}, {0.0f, 1.0f, 0.0f}, {}, {tiling, tiling}});
v.push_back({ {0.0f, y, 0.0f}, {0.0f, 1.0f, 0.0f}, {tiling, tiling} }); v.push_back({{0.0f, y, 0.0f}, {0.0f, 1.0f, 0.0f}, {}, {tiling, tiling}});
v.push_back({ {0.0f, y, z}, {0.0f, 1.0f, 0.0f}, {tiling, 0.0f} }); v.push_back({{0.0f, y, z}, {0.0f, 1.0f, 0.0f}, {}, {tiling, 0.0f}});
v.push_back({ {x, y, z}, {0.0f, 1.0f, 0.0f}, {0.0f, 0.0f} }); v.push_back({{x, y, z}, {0.0f, 1.0f, 0.0f}, {}, {0.0f, 0.0f}});
// left // left
v.push_back({ {0.0f, y, z}, {-1.0f, 0.0f, 0.0f}, {0.0f, 0.0f} }); v.push_back({{0.0f, y, z}, {-1.0f, 0.0f, 0.0f}, {}, {0.0f, 0.0f}});
v.push_back({ {0.0f, y, 0.0f}, {-1.0f, 0.0f, 0.0f}, {0.0f, tiling} }); v.push_back({{0.0f, y, 0.0f}, {-1.0f, 0.0f, 0.0f}, {}, {0.0f, tiling}});
v.push_back({ {0.0f, 0.0f, 0.0f}, {-1.0f, 0.0f, 0.0f}, {tiling, tiling} }); v.push_back({{0.0f, 0.0f, 0.0f}, {-1.0f, 0.0f, 0.0f}, {}, {tiling, tiling}});
v.push_back({ {0.0f, 0.0f, 0.0f}, {-1.0f, 0.0f, 0.0f}, {tiling, tiling} }); v.push_back({{0.0f, 0.0f, 0.0f}, {-1.0f, 0.0f, 0.0f}, {}, {tiling, tiling}});
v.push_back({ {0.0f, 0.0f, z}, {-1.0f, 0.0f, 0.0f}, {tiling, 0.0f} }); v.push_back({{0.0f, 0.0f, z}, {-1.0f, 0.0f, 0.0f}, {}, {tiling, 0.0f}});
v.push_back({ {0.0f, y, z}, {-1.0f, 0.0f, 0.0f}, {0.0f, 0.0f} }); v.push_back({{0.0f, y, z}, {-1.0f, 0.0f, 0.0f}, {}, {0.0f, 0.0f}});
// right // right
v.push_back({ {x, 0.0f, z}, {1.0f, 0.0f, 0.0f}, {0.0f, 0.0f} }); v.push_back({{x, 0.0f, z}, {1.0f, 0.0f, 0.0f}, {}, {0.0f, 0.0f}});
v.push_back({ {x, 0.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, {0.0f, tiling} }); v.push_back({{x, 0.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, {}, {0.0f, tiling}});
v.push_back({ {x, y, 0.0f}, {1.0f, 0.0f, 0.0f}, {tiling, tiling} }); v.push_back({{x, y, 0.0f}, {1.0f, 0.0f, 0.0f}, {}, {tiling, tiling}});
v.push_back({ {x, y, 0.0f}, {1.0f, 0.0f, 0.0f}, {tiling, tiling} }); v.push_back({{x, y, 0.0f}, {1.0f, 0.0f, 0.0f}, {}, {tiling, tiling}});
v.push_back({ {x, y, z}, {1.0f, 0.0f, 0.0f}, {tiling, 0.0f} }); v.push_back({{x, y, z}, {1.0f, 0.0f, 0.0f}, {}, {tiling, 0.0f}});
v.push_back({ {x, 0.0f, z}, {1.0f, 0.0f, 0.0f}, {0.0f, 0.0f} }); v.push_back({{x, 0.0f, z}, {1.0f, 0.0f, 0.0f}, {}, {0.0f, 0.0f}});
// top // top
v.push_back({ {0.0f, y, z}, {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f} }); v.push_back({{0.0f, y, z}, {0.0f, 0.0f, 1.0f}, {1.0f, 0.0f, 0.0f, 1.0f}, {0.0f, 0.0f}});
v.push_back({ {0.0f, 0.0f, z}, {0.0f, 0.0f, 1.0f}, {0.0f, tiling} }); v.push_back({{0.0f, 0.0f, z}, {0.0f, 0.0f, 1.0f}, {1.0f, 0.0f, 0.0f, 1.0f}, {0.0f, tiling}});
v.push_back({ {x, 0.0f, z}, {0.0f, 0.0f, 1.0f}, {tiling, tiling} }); v.push_back({{x, 0.0f, z}, {0.0f, 0.0f, 1.0f}, {1.0f, 0.0f, 0.0f, 1.0f}, {tiling, tiling}});
v.push_back({ {x, 0.0f, z}, {0.0f, 0.0f, 1.0f}, {tiling, tiling} }); v.push_back({{x, 0.0f, z}, {0.0f, 0.0f, 1.0f}, {1.0f, 0.0f, 0.0f, 1.0f}, {tiling, tiling}});
v.push_back({ {x, y, z}, {0.0f, 0.0f, 1.0f}, {tiling, 0.0f} }); v.push_back({{x, y, z}, {0.0f, 0.0f, 1.0f}, {1.0f, 0.0f, 0.0f, 1.0f}, {tiling, 0.0f}});
v.push_back({ {0.0f, y, z}, {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f} }); v.push_back({{0.0f, y, z}, {0.0f, 0.0f, 1.0f}, {1.0f, 0.0f, 0.0f, 1.0f}, {0.0f, 0.0f}});
// bottom // bottom
v.push_back({ {x, y, 0.0f}, {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f} }); v.push_back({{x, y, 0.0f}, {0.0f, 0.0f, -1.0f}, {}, {0.0f, 0.0f}});
v.push_back({ {x, 0.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, {0.0f, tiling} }); v.push_back({{x, 0.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, {}, {0.0f, tiling}});
v.push_back({ {0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, {tiling, tiling} }); v.push_back({{0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, {}, {tiling, tiling}});
v.push_back({ {0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, {tiling, tiling} }); v.push_back({{0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, {}, {tiling, tiling}});
v.push_back({ {0.0f, y, 0.0f}, {0.0f, 0.0f, -1.0f}, {tiling, 0.0f} }); v.push_back({{0.0f, y, 0.0f}, {0.0f, 0.0f, -1.0f}, {}, {tiling, 0.0f}});
v.push_back({ {x, y, 0.0f}, {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f} }); v.push_back({{x, y, 0.0f}, {0.0f, 0.0f, -1.0f}, {}, {0.0f, 0.0f}});
if (wind_inside) { if (wind_inside) {
for (size_t i = 0; i < v.size(); i += 3) { for (size_t i = 0; i < v.size(); i += 3) {
@ -134,5 +134,5 @@ std::unique_ptr<engine::resources::Mesh> GenCuboidMesh(engine::GFXDevice* gfx, f
} }
} }
return std::make_unique<engine::resources::Mesh>(gfx, v); return std::make_unique<engine::Mesh>(gfx, v);
} }

View File

@ -5,11 +5,11 @@
#include "resources/mesh.h" #include "resources/mesh.h"
std::unique_ptr<engine::resources::Mesh> GenSphereMesh( std::unique_ptr<engine::Mesh> GenSphereMesh(
engine::GFXDevice* gfx, float r, int detail, bool wind_inside = false, engine::GFXDevice* gfx, float r, int detail, bool wind_inside = false,
bool flip_normals = false); bool flip_normals = false);
std::unique_ptr<engine::resources::Mesh> GenCuboidMesh( std::unique_ptr<engine::Mesh> GenCuboidMesh(
engine::GFXDevice* gfx, float x, float y, float z, float tiling = 1.0f, engine::GFXDevice* gfx, float x, float y, float z, float tiling = 1.0f,
bool wind_inside = false); bool wind_inside = false);