diff --git a/doc/template.blend b/doc/template.blend new file mode 100644 index 0000000..f555060 --- /dev/null +++ b/doc/template.blend @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:13fde148182128e0bd5f516e82a2553b1e611cad546ffcf0e6ae2e4f9dbeb0cf +size 1396176 diff --git a/include/components/mesh_renderable.h b/include/components/mesh_renderable.h index 8dadf18..5b5a761 100644 --- a/include/components/mesh_renderable.h +++ b/include/components/mesh_renderable.h @@ -11,6 +11,7 @@ namespace engine { struct MeshRenderableComponent { std::shared_ptr mesh; std::shared_ptr material; + bool visible = true; // for static meshes, changes to this may require the static render list to be rebuilt }; } // namespace engine diff --git a/res/engine/shaders/fancy.frag b/res/engine/shaders/fancy.frag index 5bba92e..bae23cc 100644 --- a/res/engine/shaders/fancy.frag +++ b/res/engine/shaders/fancy.frag @@ -1,5 +1,8 @@ #version 450 +#define PI 3.1415926535897932384626433832795 +#define PI_INV 0.31830988618379067153776752674503 + layout(set = 2, binding = 0) uniform sampler2D materialSetAlbedoSampler; layout(set = 2, binding = 1) uniform sampler2D materialSetNormalSampler; layout(set = 2, binding = 2) uniform sampler2D materialSetOcclusionSampler; @@ -12,30 +15,61 @@ layout(location = 3) in vec3 fragLightPosTangentSpace; layout(location = 0) out vec4 outColor; -void main() { - - // constants - vec3 lightColor = vec3(1.0, 0.9, 0.9); - vec3 ambientColor = vec3(1.0, 0.0, 0.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.y = 1.0 - norm.y; - norm = normalize(norm * 2.0 - 1.0); - - vec3 lightDir = normalize(fragLightPosTangentSpace - fragPosTangentSpace); - vec3 viewDir = normalize(fragViewPosTangentSpace - fragPosTangentSpace); - - 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 = diffuse + ambient + specular; - outColor = vec4(min(baseColor * (lighting + emission), 1.0), 1.0); +vec3 GetNormal() { + const vec3 norm_colour = vec3(texture(materialSetNormalSampler, fragUV)); + return normalize(norm_colour * 2.0 - 1.0); } +float GGXDist(float alpha_2, float N_dot_H) { + const float num = alpha_2 * max(N_dot_H, 0.0); + const float den = PI * pow(N_dot_H * N_dot_H * (alpha_2 - 1) + 1, 2.0); + return num / den; +} + +void main() { + + const vec3 metallic_roughness = vec3(texture(materialSetMetallicRoughnessSampler, fragUV)); + const float metallic = metallic_roughness.g; + const float roughness = metallic_roughness.b; + const float roughness_2 = roughness * roughness; + + const vec3 light_colour = vec3(1.0, 1.0, 1.0) * 2.4; + const vec3 emission = vec3(0.0, 0.0, 0.0); + + const float ao = texture(materialSetOcclusionSampler, fragUV).r; + + const vec3 albedo = vec3(texture(materialSetAlbedoSampler, fragUV)); + const vec3 N = GetNormal(); + + const vec3 V = normalize(fragViewPosTangentSpace - fragPosTangentSpace); + //const vec3 L = normalize(fragLightPosTangentSpace - fragPosTangentSpace); + const vec3 L = normalize(vec3(5.0, 0.0, 3.0)); + const vec3 H = normalize(V + L); + + //const vec3 dielectric_brdf = FresnelMix(); + + //const vec3 brdf = mix(dielectric_brdf, metal_brdf, metallic); + + const float L_dot_N = max(dot(L, N), 0.000001); + const float L_dot_H = max(dot(L, H), 0.000001); + const float V_dot_H = max(dot(V, H), 0.000001); + const float V_dot_N = max(dot(V, N), 0.000001); + const float N_dot_H = max(dot(N, H), 0.000001); + + const float vis = ( max(L_dot_H, 0.0) / ( L_dot_N + sqrt(roughness_2 + (1 - roughness_2) * L_dot_N * L_dot_N) ) ) * + ( max(V_dot_H, 0.0) / ( V_dot_N + sqrt(roughness_2 + (1 - roughness_2) * V_dot_N * V_dot_N) ) ); + + const vec3 diffuse_brdf = albedo * PI_INV; + + const vec3 specular_brdf = vec3(vis * GGXDist(roughness_2, N_dot_H)); + + const vec3 dielectric_brdf = mix(diffuse_brdf, specular_brdf, 0.04 + (1 - 0.04) * pow(1 - abs(V_dot_H), 5)); + + const vec3 metal_brdf = specular_brdf * (albedo + (1 - albedo) * pow(1 - V_dot_H, 5.0) ); + + const vec3 brdf = mix(dielectric_brdf, metal_brdf, metallic); + + const vec3 lighting = brdf * light_colour * L_dot_N; + + outColor = vec4(min(emission + lighting, 1.0), 1.0); +} \ No newline at end of file diff --git a/src/application.cpp b/src/application.cpp index 7e8b0fb..91ae4bd 100644 --- a/src/application.cpp +++ b/src/application.cpp @@ -118,16 +118,63 @@ Application::Application(const char* appName, const char* appVersion, gfx::Graph GetResourcePath("engine/shaders/fancy.frag").c_str(), shaderSettings); GetResourceManager()->AddPersistent("builtin.fancy", std::move(fancyShader)); } + { + Shader::VertexParams vertParams{}; + vertParams.has_normal = true; + vertParams.has_tangent = true; + vertParams.has_uv0 = true; + Shader::ShaderSettings shaderSettings{}; + shaderSettings.vertexParams = vertParams; + shaderSettings.alpha_blending = false; + shaderSettings.cull_backface = true; + shaderSettings.write_z = false; + shaderSettings.render_order = 1; + auto skyboxShader = std::make_unique(renderer(), GetResourcePath("engine/shaders/skybox.vert").c_str(), + GetResourcePath("engine/shaders/skybox.frag").c_str(), shaderSettings); + GetResourceManager()->AddPersistent("builtin.skybox", std::move(skyboxShader)); + } /* default textures */ { - auto whiteTexture = LoadTextureFromFile(GetResourcePath("engine/textures/white.png"), gfx::SamplerInfo{}, renderer(), true); + const uint8_t pixel[4] = { 255, 255, 255, 255 }; + gfx::SamplerInfo samplerInfo{}; + samplerInfo.minify = gfx::Filter::kNearest; + samplerInfo.magnify = gfx::Filter::kNearest; + samplerInfo.mipmap = gfx::Filter::kNearest; + samplerInfo.anisotropic_filtering = false; + auto whiteTexture = std::make_unique(renderer(), pixel, 1, 1, samplerInfo, true); GetResourceManager()->AddPersistent("builtin.white", std::move(whiteTexture)); } { - auto normalTexture = LoadTextureFromFile(GetResourcePath("engine/textures/normal.png"), gfx::SamplerInfo{}, renderer(), false); + const uint8_t pixel[4] = { 0, 0, 0, 255 }; + gfx::SamplerInfo samplerInfo{}; + samplerInfo.minify = gfx::Filter::kNearest; + samplerInfo.magnify = gfx::Filter::kNearest; + samplerInfo.mipmap = gfx::Filter::kNearest; + samplerInfo.anisotropic_filtering = false; + auto blackTexture = std::make_unique(renderer(), pixel, 1, 1, samplerInfo, true); + GetResourceManager()->AddPersistent("builtin.black", std::move(blackTexture)); + } + { + const uint8_t pixel[4] = { 127, 127, 255, 255 }; + gfx::SamplerInfo samplerInfo{}; + samplerInfo.minify = gfx::Filter::kNearest; + samplerInfo.magnify = gfx::Filter::kNearest; + samplerInfo.mipmap = gfx::Filter::kNearest; + samplerInfo.anisotropic_filtering = false; + auto normalTexture = std::make_unique(renderer(), pixel, 1, 1, samplerInfo, false); GetResourceManager()->AddPersistent("builtin.normal", std::move(normalTexture)); } + { + const uint8_t pixel[4] = { 255, 0, 127, 255 }; + gfx::SamplerInfo samplerInfo{}; + samplerInfo.minify = gfx::Filter::kNearest; + samplerInfo.magnify = gfx::Filter::kNearest; + samplerInfo.mipmap = gfx::Filter::kNearest; + samplerInfo.anisotropic_filtering = false; + auto mrTexture = std::make_unique(renderer(), pixel, 1, 1, samplerInfo, false); + GetResourceManager()->AddPersistent("builtin.mr", std::move(mrTexture)); + } /* default materials */ { diff --git a/src/gfx_device_vulkan.cpp b/src/gfx_device_vulkan.cpp index 271e64a..a6ed49d 100644 --- a/src/gfx_device_vulkan.cpp +++ b/src/gfx_device_vulkan.cpp @@ -731,9 +731,9 @@ gfx::DrawBuffer* GFXDevice::BeginRender() std::array clearValues{}; // Using same value for all components enables // compression according to NVIDIA Best Practices - clearValues[0].color.float32[0] = 0.02f; - clearValues[0].color.float32[1] = 0.0f; - clearValues[0].color.float32[2] = 0.0f; + clearValues[0].color.float32[0] = 1.0f; + clearValues[0].color.float32[1] = 1.0f; + clearValues[0].color.float32[2] = 1.0f; clearValues[0].color.float32[3] = 1.0f; clearValues[1].depthStencil.depth = 1.0f; diff --git a/src/systems/mesh_render_system.cpp b/src/systems/mesh_render_system.cpp index f102c07..750f81c 100644 --- a/src/systems/mesh_render_system.cpp +++ b/src/systems/mesh_render_system.cpp @@ -50,6 +50,8 @@ void MeshRenderSystem::BuildRenderList(RenderList& render_list, bool with_static auto renderable = scene_->GetComponent(entity); + if (renderable->visible == false) continue; + const gfx::Pipeline* pipeline = renderable->material->GetShader()->GetPipeline(); render_list.emplace_back(RenderListEntry{.pipeline = pipeline, diff --git a/src/util/gltf_loader.cpp b/src/util/gltf_loader.cpp index ae98f4e..700d2ca 100644 --- a/src/util/gltf_loader.cpp +++ b/src/util/gltf_loader.cpp @@ -26,7 +26,10 @@ struct Color { namespace std { template <> struct std::hash { - std::size_t operator()(const Color& k) const { return k.r << 24 | k.g << 16 | k.b << 8 | k.a; } + std::size_t operator()(const Color& k) const + { + return static_cast(k.r) << 24 | static_cast(k.g) << 16 | static_cast(k.b) << 8 | static_cast(k.a); + } }; } // namespace std @@ -116,14 +119,14 @@ engine::Entity LoadGLTF(Scene& scene, const std::string& path, bool isStatic) const tg::Scene& s = model.scenes.at(scene_index); - /* Find which texture indices point to normal maps. */ + /* Find which texture indices point to base color maps. */ /* This must be done for the Texture constructor to know to use srgb or not. */ - std::vector tex_index_is_normal_map(model.textures.size(), false); + std::vector tex_index_is_base_color(model.textures.size(), false); for (const tg::Material& mat : model.materials) { - int texture_index = mat.normalTexture.index; + int texture_index = mat.pbrMetallicRoughness.baseColorTexture.index; if (texture_index != -1) { - assert(texture_index < tex_index_is_normal_map.size()); - tex_index_is_normal_map[texture_index] = true; + assert(texture_index < tex_index_is_base_color.size()); + tex_index_is_base_color[texture_index] = true; } } @@ -186,7 +189,8 @@ engine::Entity LoadGLTF(Scene& scene, const std::string& path, bool isStatic) const tg::Image& image = model.images.at(texture.source); if (image.as_is == false && image.bits == 8 && image.component == 4 && image.pixel_type == TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE) { // create texture on GPU - textures.back() = std::make_shared(scene.app()->renderer(), image.image.data(), image.width, image.height, samplerInfo, !tex_index_is_normal_map[texture_idx]); + textures.back() = std::make_shared(scene.app()->renderer(), image.image.data(), image.width, image.height, samplerInfo, + tex_index_is_base_color[texture_idx]); } ++texture_idx; @@ -196,6 +200,8 @@ engine::Entity LoadGLTF(Scene& scene, const std::string& path, bool isStatic) // store some 1x1 colour textures as a hack to render solid colours std::unordered_map> colour_textures; + // same for metallic roughness: + std::unordered_map> metal_rough_textures; std::vector> materials{}; materials.reserve(model.materials.size()); @@ -213,10 +219,6 @@ engine::Entity LoadGLTF(Scene& scene, const std::string& path, bool isStatic) LOG_WARN("Material {} contains an emissive texture or non-zero emissive factor. Emission is currently unsupported.", material.name); LOG_WARN("Material will be created without emission."); } - if (material.occlusionTexture.index != -1) { - LOG_WARN("Material {} contains an ambient occlusion texture which isn't supported yet.", material.name); - LOG_WARN("Material will be created without an occlusion map."); - } const auto& baseColorFactor4 = material.pbrMetallicRoughness.baseColorFactor; if (baseColorFactor4[0] != 1.0 || baseColorFactor4[1] != 1.0 || baseColorFactor4[2] != 1.0 || baseColorFactor4[3] != 1.0) { if (material.pbrMetallicRoughness.baseColorTexture.index != -1) { @@ -224,20 +226,16 @@ engine::Entity LoadGLTF(Scene& scene, const std::string& path, bool isStatic) LOG_WARN("The material's base color texture will be used as-is."); } } - if (material.pbrMetallicRoughness.metallicRoughnessTexture.index != -1) { - LOG_WARN("Material {} contains a metallic-roughness texture which isn't supported yet.", material.name); - LOG_WARN("This texture will be ignored."); - } - if (material.pbrMetallicRoughness.metallicFactor != 1.0) { - LOG_WARN("Material {} contains a metallic factor != 1.0 which isn't supported yet.", material.name); - LOG_WARN("Material will be created as fully metallic"); - } - if (material.pbrMetallicRoughness.roughnessFactor != 1.0) { - LOG_WARN("Material {} contains a roughness factor != 1.0 which isn't supported yet.", material.name); - LOG_WARN("Material will be created as fully rough"); + if (material.pbrMetallicRoughness.metallicFactor != 1.0 || material.pbrMetallicRoughness.roughnessFactor != 1.0) { + if (material.pbrMetallicRoughness.metallicRoughnessTexture.index != -1) { + LOG_WARN("Material {} contains a metallic and/or roughness multiplier which isn't supported yet.", material.name); + LOG_WARN("The material's metallic-roughness texture will be used as-is."); + } } materials.emplace_back(std::make_shared(scene.app()->renderer(), scene.app()->GetResource("builtin.fancy"))); + + // base color materials.back()->SetAlbedoTexture(scene.app()->GetResource("builtin.white")); if (material.pbrMetallicRoughness.baseColorTexture.index != -1) { if (material.pbrMetallicRoughness.baseColorTexture.texCoord == 0) { @@ -252,11 +250,7 @@ engine::Entity LoadGLTF(Scene& scene, const std::string& path, bool isStatic) LOG_INFO("Creating a base-color texture..."); Color c(baseColorFactor4); if (colour_textures.contains(c) == false) { - uint8_t pixel[4]; - pixel[0] = c.r; - pixel[1] = c.g; - pixel[2] = c.b; - pixel[3] = c.a; + const uint8_t pixel[4] = {c.r, c.g, c.b, c.a}; gfx::SamplerInfo samplerInfo{}; samplerInfo.minify = gfx::Filter::kNearest; samplerInfo.magnify = gfx::Filter::kNearest; @@ -267,6 +261,48 @@ engine::Entity LoadGLTF(Scene& scene, const std::string& path, bool isStatic) materials.back()->SetAlbedoTexture(colour_textures.at(c)); } + // metallic roughness + materials.back()->SetMetallicRoughnessTexture(scene.app()->GetResource("builtin.white")); // default metal = 1.0, rough = 1.0 + if (material.pbrMetallicRoughness.metallicRoughnessTexture.index != -1) { + if (material.pbrMetallicRoughness.metallicRoughnessTexture.texCoord == 0) { + LOG_INFO("Setting metallic roughness texture!"); + materials.back()->SetMetallicRoughnessTexture(textures.at(material.pbrMetallicRoughness.metallicRoughnessTexture.index)); + } + else { + LOG_WARN("Material {} metallic roughness texture specifies a UV channel other than zero which is unsupported.", material.name); + LOG_WARN("Material will be created with a default metallic roughness"); + } + } + else { + LOG_INFO("Creating a metallic-roughness texture..."); + const std::vector mr_values{1.0f, material.pbrMetallicRoughness.metallicFactor, material.pbrMetallicRoughness.roughnessFactor, 1.0f}; + Color mr(mr_values); + if (metal_rough_textures.contains(mr) == false) { + const uint8_t pixel[4] = {mr.r, mr.g, mr.b, mr.a}; + gfx::SamplerInfo samplerInfo{}; + samplerInfo.minify = gfx::Filter::kNearest; + samplerInfo.magnify = gfx::Filter::kNearest; + samplerInfo.mipmap = gfx::Filter::kNearest; + samplerInfo.anisotropic_filtering = false; + metal_rough_textures.emplace(std::make_pair(mr, std::make_shared(scene.app()->renderer(), pixel, 1, 1, samplerInfo, false))); + } + materials.back()->SetMetallicRoughnessTexture(metal_rough_textures.at(mr)); + } + + // occlusion texture + materials.back()->SetOcclusionTexture(scene.app()->GetResource("builtin.white")); // R=255 means no AO so white will work + if (material.occlusionTexture.index != -1) { + if (material.occlusionTexture.texCoord == 0) { + LOG_INFO("Setting occlusion texture!"); + materials.back()->SetOcclusionTexture(textures.at(material.occlusionTexture.index)); + } + else { + LOG_WARN("Material {} occlusion texture specifies a UV channel other than zero which is unsupported.", material.name); + LOG_WARN("Material will be created with no ambient occlusion"); + } + } + + // normal map materials.back()->SetNormalTexture(scene.app()->GetResource("builtin.normal")); if (material.normalTexture.index != -1) { if (material.normalTexture.texCoord == 0) { @@ -412,7 +448,7 @@ engine::Entity LoadGLTF(Scene& scene, const std::string& path, bool isStatic) mts_interface.m_getNumVerticesOfFace = [](const SMikkTSpaceContext*, const int) -> int { return 3; }; mts_interface.m_getPosition = [](const SMikkTSpaceContext* pContext, float fvPosOut[], const int iFace, const int iVert) -> void { const MeshData* const meshData = static_cast(pContext->m_pUserData); - const size_t i = iFace * 3 + iVert; + const size_t i = static_cast(iFace) * 3 + static_cast(iVert); assert(i < meshData->num_indices); const size_t vertex_index = meshData->indices[i]; const glm::vec3 pos = meshData->positions->operator[](vertex_index); @@ -422,7 +458,7 @@ engine::Entity LoadGLTF(Scene& scene, const std::string& path, bool isStatic) }; mts_interface.m_getNormal = [](const SMikkTSpaceContext* pContext, float fvNormOut[], const int iFace, const int iVert) -> void { const MeshData* const meshData = static_cast(pContext->m_pUserData); - const size_t i = iFace * 3 + iVert; + const size_t i = static_cast(iFace) * 3 + static_cast(iVert); assert(i < meshData->num_indices); const size_t vertex_index = meshData->indices[i]; const glm::vec3 norm = meshData->normals->operator[](vertex_index); @@ -432,7 +468,7 @@ engine::Entity LoadGLTF(Scene& scene, const std::string& path, bool isStatic) }; mts_interface.m_getTexCoord = [](const SMikkTSpaceContext* pContext, float fvTexcOut[], const int iFace, const int iVert) -> void { const MeshData* const meshData = static_cast(pContext->m_pUserData); - const size_t i = iFace * 3 + iVert; + const size_t i = static_cast(iFace) * 3 + static_cast(iVert); assert(i < meshData->num_indices); const size_t vertex_index = meshData->indices[i]; const glm::vec2 uv = meshData->uvs->operator[](vertex_index); @@ -442,7 +478,7 @@ engine::Entity LoadGLTF(Scene& scene, const std::string& path, bool isStatic) mts_interface.m_setTSpaceBasic = [](const SMikkTSpaceContext* pContext, const float fvTangent[], const float fSign, const int iFace, const int iVert) -> void { MeshData* const meshData = static_cast(pContext->m_pUserData); - const size_t i = iFace * 3 + iVert; + const size_t i = static_cast(iFace) * 3 + static_cast(iVert); assert(i < meshData->num_indices); const size_t vertex_index = meshData->indices[i]; @@ -470,7 +506,7 @@ engine::Entity LoadGLTF(Scene& scene, const std::string& path, bool isStatic) std::vector vertex_data_out(num_indices); // initialised to zeros const int num_unq_vertices = WeldMesh(remap_table.data(), reinterpret_cast(vertex_data_out.data()), - reinterpret_cast(vertices.data()), static_cast(num_indices), Vertex::FloatsPerVertex()); + reinterpret_cast(vertices.data()), static_cast(num_indices), Vertex::FloatsPerVertex()); assert(num_unq_vertices >= 0); // get new vertices into the vector diff --git a/src/vulkan/swapchain.cpp b/src/vulkan/swapchain.cpp index ec5b482..1ccb65b 100644 --- a/src/vulkan/swapchain.cpp +++ b/src/vulkan/swapchain.cpp @@ -42,6 +42,9 @@ namespace engine { sc->surfaceFormat = format; // prefer using srgb non linear colors } } + if (sc->surfaceFormat.colorSpace != VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) { + LOG_ERROR("Swapchain not using an SRGB surface!!!"); + } // check there is at least one supported present mode uint32_t surfacePresentModeCount = 0; diff --git a/test/res/models/bottle.glb b/test/res/models/bottle.glb new file mode 100644 index 0000000..a1f63ec Binary files /dev/null and b/test/res/models/bottle.glb differ diff --git a/test/res/models/monke.glb b/test/res/models/monke.glb new file mode 100644 index 0000000..eaf0cd2 Binary files /dev/null and b/test/res/models/monke.glb differ diff --git a/test/res/textures/bricks-mortar-albedo.png b/test/res/textures/bricks-mortar-albedo.png new file mode 100644 index 0000000..3f0d869 Binary files /dev/null and b/test/res/textures/bricks-mortar-albedo.png differ diff --git a/test/res/textures/bricks-mortar-normal.png b/test/res/textures/bricks-mortar-normal.png new file mode 100644 index 0000000..a00970d Binary files /dev/null and b/test/res/textures/bricks-mortar-normal.png differ diff --git a/test/res/textures/bricks-mortar-roughness.png b/test/res/textures/bricks-mortar-roughness.png new file mode 100644 index 0000000..af594eb Binary files /dev/null and b/test/res/textures/bricks-mortar-roughness.png differ diff --git a/test/src/game.cpp b/test/src/game.cpp index cd917d8..1084ba2 100644 --- a/test/src/game.cpp +++ b/test/src/game.cpp @@ -59,168 +59,78 @@ void PlayGame(GameSettings settings) app.window()->SetRelativeMouseMode(true); ConfigureInputs(*app.input_manager()); - engine::Scene* my_scene = app.scene_manager()->CreateEmptyScene(); + engine::Scene* start_scene = app.scene_manager()->CreateEmptyScene(); { + /* create camera */ + engine::Entity camera = start_scene->CreateEntity("camera"); - { /* create camera */ - engine::Entity camera = my_scene->CreateEntity("camera"); + /* as of right now, the entity with tag 'camera' is used to build the view + * matrix */ - /* as of right now, the entity with tag 'camera' is used to build the view - * matrix */ + auto camera_transform = start_scene->GetComponent(camera); + camera_transform->position = {0.0f, 0.0f, 10.0f}; - auto camera_transform = my_scene->GetComponent(camera); - camera_transform->position = {0.0f, 0.0f, 10.0f}; + start_scene->RegisterComponent(); + start_scene->RegisterSystem(); + start_scene->AddComponent(camera); + } - my_scene->RegisterComponent(); - my_scene->RegisterSystem(); - my_scene->AddComponent(camera); - } + engine::Scene* main_scene = app.scene_manager()->CreateEmptyScene(); + { + /* create camera */ + engine::Entity camera = main_scene->CreateEntity("camera"); - { /* floor */ - [[maybe_unused]] engine::Entity floor = engine::util::LoadMeshFromFile(my_scene, app.GetResourcePath("models/terrain.dae"), true); - } + /* as of right now, the entity with tag 'camera' is used to build the view + * matrix */ -#if 0 + auto camera_transform = main_scene->GetComponent(camera); + camera_transform->position = {-5.0f, -10.0f, 4.0f}; - /* shared resources */ - auto grass_texture = engine::LoadTextureFromFile(app.GetResourcePath("textures/grass.png"), engine::Texture::Filtering::kAnisotropic, app.renderer()); + main_scene->RegisterComponent(); + main_scene->RegisterSystem(); + main_scene->AddComponent(camera); - std::shared_ptr sky_texture = engine::LoadTextureFromFile(app.GetResourcePath("textures/sky.jpg"), engine::Texture::Filtering::kAnisotropic, app.renderer()); + /* floor */ + engine::Entity floor = main_scene->CreateEntity("floor", 0, glm::vec3{-50.0f, -50.0f, 0.0f}); + auto floor_renderable = main_scene->AddComponent(floor); + floor_renderable->mesh = GenCuboidMesh(app.renderer()->GetDevice(), 100.0f, 100.0f, 0.1f, 50.0f); + floor_renderable->material = std::make_unique(app.renderer(), app.GetResource("builtin.fancy")); + std::shared_ptr floor_albedo = + engine::LoadTextureFromFile(app.GetResourcePath("textures/bricks-mortar-albedo.png"), engine::gfx::SamplerInfo{}, app.renderer()); + std::shared_ptr floor_normal = + engine::LoadTextureFromFile(app.GetResourcePath("textures/bricks-mortar-normal.png"), engine::gfx::SamplerInfo{}, app.renderer(), false); + std::shared_ptr floor_mr = + engine::LoadTextureFromFile(app.GetResourcePath("textures/bricks-mortar-roughness.png"), engine::gfx::SamplerInfo{}, app.renderer(), false); + floor_renderable->material->SetAlbedoTexture(floor_albedo); + floor_renderable->material->SetNormalTexture(floor_normal); + floor_renderable->material->SetMetallicRoughnessTexture(floor_mr); + floor_renderable->material->SetOcclusionTexture(app.GetResource("builtin.white")); + floor_renderable->visible = false; + + + engine::Entity normal_map_test = engine::util::LoadGLTF(*main_scene, app.GetResourcePath("models/normalmaptest.glb")); + main_scene->GetComponent(normal_map_test)->position += glm::vec3{-10.0f, 0.0f, 1.0f}; + + engine::Entity monke = engine::util::LoadGLTF(*main_scene, app.GetResourcePath("models/monke.glb")); + + engine::Entity bottle = engine::util::LoadGLTF(*main_scene, app.GetResourcePath("models/bottle.glb")); + main_scene->GetComponent(bottle)->scale *= 50.0f; + main_scene->GetComponent(bottle)->position.z += 50.0f;; /* skybox */ - { - engine::Entity skybox = my_scene->CreateEntity("skybox"); - - auto skybox_renderable = my_scene->AddComponent(skybox); - skybox_renderable->material = std::make_unique(app.GetResource("builtin.skybox")); - skybox_renderable->material->texture_ = sky_texture; - skybox_renderable->mesh = GenCuboidMesh(app.renderer()->GetDevice(), 10.0f, 10.0f, 10.0f, 1.0f, true); - - auto skybox_transform = my_scene->GetComponent(skybox); - skybox_transform->is_static = true; - skybox_transform->position = {-5.0f, -5.0f, -5.0f}; - } - - /* building */ - { - auto cobbleHouse = engine::util::LoadMeshFromFile(my_scene, app.GetResourcePath("models/cobble_house/cobble_house.dae"), false); - my_scene->GetComponent(cobbleHouse)->position += glm::vec3{33.0f, 35.0f, 0.1f}; - auto cobbleCustom = my_scene->AddComponent(cobbleHouse); - cobbleCustom->onInit = [](void) { LOG_INFO("Cobble house spin component initialised!"); }; - cobbleCustom->onUpdate = [&](float ts) { - static auto t = my_scene->GetComponent(cobbleHouse); - t->rotation *= glm::angleAxis(ts, glm::vec3{0.0f, 0.0f, 1.0f}); - }; - } - - { - engine::Entity cube = my_scene->CreateEntity("cube", 0, glm::vec3{40.0f, 10.0f, 5.0f}); - auto cubeRenderable = my_scene->AddComponent(cube); - cubeRenderable->mesh = GenCuboidMesh(app.renderer()->GetDevice(), 1.0f, 1.0f, 1.0f); - cubeRenderable->material = std::make_unique(app.GetResource("builtin.standard")); - cubeRenderable->material->texture_ = - engine::LoadTextureFromFile(app.GetResourcePath("textures/uvcheck.png"), engine::Texture::Filtering::kAnisotropic, app.renderer()); - } - - /* some text */ - { - engine::Entity textbox = my_scene->CreateEntity("textbox", 0, glm::vec3{0.0f, 0.8f, 0.0f}); - auto textboxComponent = my_scene->AddComponent(textbox); - textboxComponent->onInit = [](void) { LOG_DEBUG("Textbox custom component initialised!"); }; - - textboxComponent->onUpdate = [&](float ts) { - static float time_elapsed; - time_elapsed += ts; - if (time_elapsed >= 1.0f) { - time_elapsed = 0.0f; - } - }; - } - - engine::util::LoadMeshFromFile(my_scene, app.GetResourcePath("models/MY_AXES.dae"), true); - my_scene->GetComponent(engine::util::LoadMeshFromFile(my_scene, app.GetResourcePath("models/uvcheck.dae"), true)) - ->position += glm::vec3{20.0f, 20.0f, 20.0f}; - - /* teapot */ - my_scene->GetComponent(engine::util::LoadMeshFromFile(my_scene, app.GetResourcePath("models/teapot.dae"), true)) - ->position += glm::vec3{10.0f, 10.0f, 10.0f}; - - // engine::util::LoadGLTF(*my_scene, app.GetResourcePath("engine/models/test/test.gltf")); - -#endif + engine::Entity skybox = main_scene->CreateEntity("skybox"); + auto skybox_transform = main_scene->GetComponent(skybox); + skybox_transform->is_static = true; + skybox_transform->position = { -5.0f, -5.0f, -5.0f }; + auto skybox_renderable = main_scene->AddComponent(skybox); + skybox_renderable->mesh = GenCuboidMesh(app.renderer()->GetDevice(), 10.0f, 10.0f, 10.0f, 1.0f, true); + skybox_renderable->material = std::make_unique(app.renderer(), app.GetResource("builtin.skybox")); + skybox_renderable->material->SetAlbedoTexture(app.GetResource("builtin.black")); } - engine::Scene* scene2 = app.scene_manager()->CreateEmptyScene(); - { + start_scene->GetSystem()->next_scene_ = main_scene; + main_scene->GetSystem()->next_scene_ = start_scene; - { /* 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(camera); - camera_transform->position = {0.0f, 0.0f, 10.0f}; - - scene2->RegisterComponent(); - scene2->RegisterSystem(); - scene2->AddComponent(camera); - } - - { - /* axes */ - auto axes = engine::util::LoadMeshFromFile(scene2, app.GetResourcePath("models/MY_AXES.dae"), true); - scene2->GetComponent(axes)->position += glm::vec3{20.0f, 20.0f, 0.0f}; - } - - { /* floor */ - engine::Entity floor = scene2->CreateEntity("floor", 0, glm::vec3{-50.0f, -50.0f, 0.0f}); - auto floor_renderable = scene2->AddComponent(floor); - floor_renderable->mesh = GenCuboidMesh(app.renderer()->GetDevice(), 100.0f, 100.0f, 0.1f, 100.0f); - floor_renderable->material = std::make_unique(app.renderer(), app.GetResource("builtin.fancy")); - std::shared_ptr albedo_texture = - engine::LoadTextureFromFile(app.GetResourcePath("textures/brickwall_albedo.jpg"), engine::gfx::SamplerInfo{}, app.renderer()); - std::shared_ptr normal_texture = - engine::LoadTextureFromFile(app.GetResourcePath("textures/brickwall_normal.jpg"), engine::gfx::SamplerInfo{}, app.renderer(), false); - floor_renderable->material->SetAlbedoTexture(albedo_texture); - floor_renderable->material->SetNormalTexture(normal_texture); - } - - { /* teapots */ - auto teapot = engine::util::LoadGLTF(*scene2, app.GetResourcePath("models/teapot_with_tangents.glb")); - scene2->GetComponent(teapot)->scale *= 10.0f; - auto teapot2 = engine::util::LoadGLTF(*scene2, app.GetResourcePath("models/teapot.glb")); - scene2->GetComponent(teapot2)->scale *= 10.0f; - scene2->GetComponent(teapot2)->position.z += 10.0f; - auto custom = scene2->AddComponent(teapot2); - custom->onInit = [](void) { return; }; - custom->onUpdate = [&](float dt) { - dt *= 0.1f; - scene2->GetComponent(teapot2)->rotation *= glm::angleAxis(dt, glm::vec3{0.0f, 1.0f, 0.0f}); - //scene2->GetComponent(teapot2)->rotation = glm::quat(1.0f, 0.0f, 0.0f, 0.0f); - scene2->GetComponent(teapot)->rotation *= glm::angleAxis(dt, glm::vec3{0.0f, 1.0f, 0.0f}); - }; - } - - { - auto redcube = engine::util::LoadGLTF(*scene2, app.GetResourcePath("models/redcube.glb")); - } - - auto normalmaptest = engine::util::LoadGLTF(*scene2, app.GetResourcePath("models/normalmaptest.glb")); - scene2->GetComponent(normalmaptest)->position += glm::vec3{-10.0f, 0.0f, 1.0f}; - auto normalmaptest_notang = engine::util::LoadGLTF(*scene2, app.GetResourcePath("models/normalmaptest_notang.glb")); - scene2->GetComponent(normalmaptest_notang)->position += glm::vec3{-10.0f, 10.0f, 1.0f}; - auto custom = scene2->AddComponent(normalmaptest); - custom->onInit = [](void) { return; }; - custom->onUpdate = [&](float dt) { - scene2->GetComponent(normalmaptest)->rotation *= glm::angleAxis(dt, glm::vec3{ 0.0f, 0.0f, 1.0f }); - scene2->GetComponent(normalmaptest_notang)->rotation *= glm::angleAxis(dt, glm::vec3{ 0.0f, 0.0f, 1.0f }); - }; - } - - my_scene->GetSystem()->next_scene_ = scene2; - scene2->GetSystem()->next_scene_ = my_scene; - - app.scene_manager()->SetActiveScene(my_scene); + app.scene_manager()->SetActiveScene(start_scene); app.GameLoop(); }