├── android ├── gltf │ ├── .gitignore │ ├── src │ │ └── main │ │ │ ├── res │ │ │ ├── values │ │ │ │ ├── strings.xml │ │ │ │ ├── colors.xml │ │ │ │ └── styles.xml │ │ │ ├── mipmap-hdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ ├── ic_launcher_round.png │ │ │ │ └── ic_launcher_foreground.png │ │ │ ├── mipmap-mdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ ├── ic_launcher_round.png │ │ │ │ └── ic_launcher_foreground.png │ │ │ ├── mipmap-xhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ ├── ic_launcher_round.png │ │ │ │ └── ic_launcher_foreground.png │ │ │ ├── mipmap-xxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ ├── ic_launcher_round.png │ │ │ │ └── ic_launcher_foreground.png │ │ │ ├── mipmap-xxxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ ├── ic_launcher_round.png │ │ │ │ └── ic_launcher_foreground.png │ │ │ ├── mipmap-anydpi-v26 │ │ │ │ ├── ic_launcher.xml │ │ │ │ └── ic_launcher_round.xml │ │ │ └── drawable │ │ │ │ └── ic_launcher_background.xml │ │ │ └── AndroidManifest.xml │ ├── proguard-rules.pro │ └── build.gradle ├── settings.gradle ├── vulkan_wrapper │ └── CMakeLists.txt ├── .gitignore ├── CMakeLists.txt ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── common │ ├── CMakeLists.txt │ ├── android_common.h │ └── android_common.cpp ├── build.gradle ├── gradle.properties ├── gradlew.bat └── gradlew ├── docs └── .gitignore ├── README.md ├── ci-script ├── .gitignore ├── lavos ├── glsl │ ├── material │ │ ├── common.glsl │ │ ├── common_frag.glsl │ │ ├── common_camera.glsl │ │ ├── lighting_phong.glsl │ │ ├── shadow.vf.shader │ │ ├── unlit.vf.shader │ │ ├── common_vert.glsl │ │ ├── point_cloud.vf.shader │ │ ├── gouraud.vf.shader │ │ ├── common_lighting.glsl │ │ └── phong.vf.shader │ ├── common_glsl_cpp.h │ └── lib │ │ └── msm.glsl ├── cmake │ ├── generate_resources_src.cmake.in │ ├── FindShaderc.cmake │ ├── ResourceGenerator_header.h.in │ ├── ResourceGenerator_source.cpp.in │ ├── ShaderResources.cmake │ └── ResourceGenerator.cmake ├── src │ ├── scene.cpp │ ├── sub_renderer.cpp │ ├── component │ │ ├── directional_light.cpp │ │ ├── transform_component.cpp │ │ ├── fp_controller.cpp │ │ ├── mesh_component.cpp │ │ └── spot_light.cpp │ ├── render_config.cpp │ ├── buffer.cpp │ ├── thirdparty_impl.cpp │ ├── light_collection.cpp │ ├── log.cpp │ ├── shader_load.cpp │ ├── texture.cpp │ ├── mesh.cpp │ ├── material │ │ ├── point_cloud_material.cpp │ │ ├── material.cpp │ │ ├── gouraud_material.cpp │ │ ├── unlit_material.cpp │ │ └── material_instance.cpp │ ├── glm_stream.h │ ├── node.cpp │ ├── render_target.cpp │ └── image.cpp ├── include │ └── lavos │ │ ├── shader_load.h │ │ ├── glm_config.h │ │ ├── component │ │ ├── component.h │ │ ├── directional_light.h │ │ ├── fp_controller.h │ │ ├── mesh_component.h │ │ ├── transform_component.h │ │ ├── spot_light.h │ │ ├── point_cloud_component.h │ │ └── camera.h │ │ ├── log.h │ │ ├── sub_renderer.h │ │ ├── light_collection.h │ │ ├── buffer.h │ │ ├── scene.h │ │ ├── render_config.h │ │ ├── asset_container.h │ │ ├── texture.h │ │ ├── mesh.h │ │ ├── material │ │ ├── unlit_material.h │ │ ├── gouraud_material.h │ │ ├── phong_material.h │ │ ├── point_cloud_material.h │ │ ├── material_instance.h │ │ └── material.h │ │ ├── renderable.h │ │ ├── image.h │ │ ├── point_cloud.h │ │ ├── spot_light_shadow.h │ │ ├── swapchain.h │ │ ├── spot_light_shadow_renderer.h │ │ ├── vertex.h │ │ ├── material_pipeline_manager.h │ │ ├── render_target.h │ │ ├── node.h │ │ ├── engine.h │ │ └── renderer.h └── CMakeLists.txt ├── shell ├── CMakeLists.txt ├── qt │ ├── include │ │ ├── platform.h │ │ └── lavos_window.h │ ├── CMakeLists.txt │ └── src │ │ ├── platform.cpp │ │ └── lavos_window.cpp └── glfw │ ├── CMakeLists.txt │ └── include │ └── window_application.h ├── demos ├── 2d │ ├── CMakeLists.txt │ └── 2d.cpp ├── gltf │ ├── CMakeLists.txt │ └── gltf.cpp ├── room │ └── CMakeLists.txt ├── firstperson │ ├── CMakeLists.txt │ └── firstperson.cpp ├── qt_shell │ ├── CMakeLists.txt │ ├── lavos_renderer.h │ ├── main.cpp │ └── lavos_renderer.cpp ├── qt_qvulkanwindow │ ├── CMakeLists.txt │ ├── main.cpp │ ├── mainwindow.cpp │ └── mainwindow.h ├── point_cloud │ ├── CMakeLists.txt │ └── point_cloud.cpp └── CMakeLists.txt ├── Dockerfile ├── .gitmodules ├── .github └── workflows │ └── ci.yml ├── cmake └── FindVulkanHPP.cmake └── CMakeLists.txt /android/gltf/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /android/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = "vulkan-android" 2 | include ':gltf' -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | Makefile 2 | build/ 3 | html/ 4 | latex/ 5 | source/ 6 | xml/ 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Lavos 2 | 3 | This repo has been moved to: https://git.sr.ht/~thestr4ng3r/lavos 4 | -------------------------------------------------------------------------------- /ci-script: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | set -x 5 | 6 | mkdir build && cd build 7 | cmake .. 8 | make -j8 9 | -------------------------------------------------------------------------------- /android/gltf/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Vulkan 3 | 4 | -------------------------------------------------------------------------------- /android/vulkan_wrapper/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_library(vulkan_wrapper STATIC 3 | vulkan_wrapper.cpp 4 | vulkan_wrapper.h) -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | build 3 | cmake-build-* 4 | *.swp 5 | *.spv 6 | raw/ 7 | /thirdparty/vulkansdk* 8 | /thirdparty/shaderc* 9 | -------------------------------------------------------------------------------- /android/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea 5 | .DS_Store 6 | /build 7 | /captures 8 | .externalNativeBuild 9 | -------------------------------------------------------------------------------- /android/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | #add_subdirectory(vulkan_wrapper) 3 | add_subdirectory(common) 4 | 5 | #add_subdirectory("${MODULE_NAME}") -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thestr4ng3r/lavos/HEAD/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /lavos/glsl/material/common.glsl: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _MATERIAL_COMMON_GLSL 3 | #define _MATERIAL_COMMON_GLSL 4 | 5 | #include "../common_glsl_cpp.h" 6 | 7 | #endif -------------------------------------------------------------------------------- /android/gltf/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thestr4ng3r/lavos/HEAD/android/gltf/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/gltf/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thestr4ng3r/lavos/HEAD/android/gltf/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/gltf/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thestr4ng3r/lavos/HEAD/android/gltf/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/gltf/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thestr4ng3r/lavos/HEAD/android/gltf/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /lavos/cmake/generate_resources_src.cmake.in: -------------------------------------------------------------------------------- 1 | 2 | include("@RESOURCE_GENERATOR_INCLUDE@") 3 | 4 | generate_resources(GENERATE_SOURCE @GENERATE_RESOURCES_ARGS@) 5 | -------------------------------------------------------------------------------- /android/gltf/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thestr4ng3r/lavos/HEAD/android/gltf/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /shell/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | if(LAVOS_BUILD_SHELL_GLFW) 3 | add_subdirectory(glfw) 4 | endif() 5 | 6 | if(LAVOS_BUILD_SHELL_QT) 7 | add_subdirectory(qt) 8 | endif() -------------------------------------------------------------------------------- /android/gltf/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thestr4ng3r/lavos/HEAD/android/gltf/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/gltf/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thestr4ng3r/lavos/HEAD/android/gltf/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/gltf/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thestr4ng3r/lavos/HEAD/android/gltf/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/gltf/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thestr4ng3r/lavos/HEAD/android/gltf/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/gltf/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thestr4ng3r/lavos/HEAD/android/gltf/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/gltf/src/main/res/mipmap-hdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thestr4ng3r/lavos/HEAD/android/gltf/src/main/res/mipmap-hdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /android/gltf/src/main/res/mipmap-mdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thestr4ng3r/lavos/HEAD/android/gltf/src/main/res/mipmap-mdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /android/gltf/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thestr4ng3r/lavos/HEAD/android/gltf/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /android/gltf/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thestr4ng3r/lavos/HEAD/android/gltf/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /android/gltf/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thestr4ng3r/lavos/HEAD/android/gltf/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /lavos/src/scene.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "lavos/scene.h" 3 | 4 | lavos::Scene::Scene() 5 | { 6 | root_node.is_root = true; 7 | } 8 | 9 | lavos::Scene::~Scene() 10 | { 11 | 12 | } 13 | -------------------------------------------------------------------------------- /lavos/src/sub_renderer.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | #include "lavos/sub_renderer.h" 5 | 6 | lavos::SubRenderer::SubRenderer(lavos::Engine *engine) : engine(engine) 7 | { 8 | } 9 | -------------------------------------------------------------------------------- /lavos/glsl/material/common_frag.glsl: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _MATERIAL_COMMON_FRAG_GLSL 3 | #define _MATERIAL_COMMON_FRAG_GLSL 4 | 5 | #include "common.glsl" 6 | 7 | layout(location = 0) out vec4 out_color; 8 | 9 | #endif -------------------------------------------------------------------------------- /demos/2d/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | set(SOURCE_FILES 3 | 2d.cpp) 4 | 5 | add_executable(2d ${SOURCE_FILES}) 6 | target_link_libraries(2d 7 | lavos 8 | lavos_shell_glfw 9 | glfw 10 | ${Vulkan_LIBRARIES}) -------------------------------------------------------------------------------- /demos/gltf/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | set(SOURCE_FILES 3 | gltf.cpp) 4 | 5 | add_executable(gltf ${SOURCE_FILES}) 6 | target_link_libraries(gltf 7 | lavos 8 | lavos_shell_glfw 9 | glfw 10 | ${Vulkan_LIBRARIES}) -------------------------------------------------------------------------------- /demos/room/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | set(SOURCE_FILES 3 | room.cpp) 4 | 5 | add_executable(room ${SOURCE_FILES}) 6 | target_link_libraries(room 7 | lavos 8 | lavos_shell_glfw 9 | glfw 10 | ${Vulkan_LIBRARIES}) -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM archlinux:latest 2 | MAINTAINER thestr4ng3r 3 | 4 | RUN pacman --noconfirm -Syu \ 5 | base-devel \ 6 | git \ 7 | vulkan-headers \ 8 | shaderc \ 9 | cmake \ 10 | vulkan-icd-loader \ 11 | glfw-x11 12 | 13 | CMD [] 14 | -------------------------------------------------------------------------------- /demos/firstperson/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | set(SOURCE_FILES 3 | firstperson.cpp) 4 | 5 | add_executable(firstperson ${SOURCE_FILES}) 6 | target_link_libraries(firstperson 7 | lavos 8 | lavos_shell_glfw 9 | glfw 10 | ${Vulkan_LIBRARIES}) -------------------------------------------------------------------------------- /android/gltf/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | 7 | -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Sat Sep 02 11:00:47 CEST 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip 7 | -------------------------------------------------------------------------------- /lavos/include/lavos/shader_load.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _DEMO_COMMON_SHADER_LOAD_H 3 | #define _DEMO_COMMON_SHADER_LOAD_H 4 | 5 | #include 6 | #include 7 | 8 | namespace lavos 9 | { 10 | const uint32_t *GetSPIRVShader(const std::string shader, size_t *size); 11 | } 12 | 13 | #endif -------------------------------------------------------------------------------- /lavos/src/component/directional_light.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "lavos/component/directional_light.h" 3 | 4 | using namespace lavos; 5 | 6 | DirectionalLight::DirectionalLight(glm::vec3 intensity) 7 | : intensity(intensity) 8 | { 9 | } 10 | 11 | DirectionalLight::~DirectionalLight() 12 | { 13 | } 14 | -------------------------------------------------------------------------------- /lavos/include/lavos/glm_config.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef LAVOS_GLM_CONFIG_H 3 | #define LAVOS_GLM_CONFIG_H 4 | 5 | #define GLM_FORCE_RADIANS 6 | #define GLM_FORCE_DEPTH_ZERO_TO_ONE 7 | #define GLM_FORCE_SWIZZLE 8 | 9 | // TODO: remove when not necessary anymore 10 | #define GLM_ENABLE_EXPERIMENTAL 11 | 12 | #endif //VULKAN_GLM_CONFIG_H 13 | -------------------------------------------------------------------------------- /lavos/src/component/transform_component.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "lavos/component/transform_component.h" 3 | 4 | using namespace lavos; 5 | 6 | void TransformComp::SetLookAt(glm::vec3 target, glm::vec3 up) 7 | { 8 | glm::mat4 m = glm::lookAt(translation, target, up); 9 | m = glm::inverse(m); 10 | rotation = glm::toQuat(m); 11 | } 12 | -------------------------------------------------------------------------------- /android/gltf/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /android/gltf/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /shell/qt/include/platform.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef LAVOS_SHELL_QT_PLATFORM_H 3 | #define LAVOS_SHELL_QT_PLATFORM_H 4 | 5 | #include 6 | #include 7 | 8 | namespace lavos { namespace shell { namespace qt 9 | { 10 | 11 | std::set GetSurfaceExtensionsForPlatform(); 12 | 13 | }}} 14 | 15 | #endif //LAVOS_SHELL_QT_PLATFORM_H 16 | -------------------------------------------------------------------------------- /lavos/glsl/material/common_camera.glsl: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _MATERIAL_COMMON_CAMERA_GLSL 3 | #define _MATERIAL_COMMON_CAMERA_GLSL 4 | 5 | #include "common.glsl" 6 | 7 | layout(set = DESCRIPTOR_SET_INDEX_COMMON, binding = DESCRIPTOR_SET_COMMON_BINDING_CAMERA_BUFFER, std140) uniform CameraBuffer 8 | { 9 | vec3 position; 10 | } camera_uni; 11 | 12 | #endif -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "thirdparty/glm"] 2 | path = thirdparty/glm 3 | url = https://github.com/g-truc/glm.git 4 | [submodule "demos/data"] 5 | path = demos/data 6 | url = https://github.com/thestr4ng3r/lavos-demo-assets.git 7 | [submodule "thirdparty/vma"] 8 | path = thirdparty/vma 9 | url = https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git 10 | -------------------------------------------------------------------------------- /lavos/cmake/FindShaderc.cmake: -------------------------------------------------------------------------------- 1 | # FindShaderc 2 | # ------- 3 | # 4 | # This will will define the following variables: 5 | # 6 | # SHADERC_FOUND - true if Shaderc has been found 7 | # SHADERC_GLSLC - the glslc executable 8 | 9 | find_program(Shaderc_GLSLC glslc) 10 | 11 | include(FindPackageHandleStandardArgs) 12 | find_package_handle_standard_args(Shaderc REQUIRED_VARS Shaderc_GLSLC) -------------------------------------------------------------------------------- /lavos/src/render_config.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "lavos/render_config.h" 3 | 4 | using namespace lavos; 5 | 6 | RenderConfig RenderConfigBuilder::Build() 7 | { 8 | RenderConfig config; 9 | config.material_render_modes = { Material::DefaultRenderMode::ColorForward }; 10 | 11 | if(shadow_enabled) 12 | config.material_render_modes.push_back(Material::DefaultRenderMode::Shadow); 13 | 14 | return config; 15 | } 16 | -------------------------------------------------------------------------------- /shell/glfw/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | set(SOURCE_FILES 3 | include/window_application.h 4 | src/window_application.cpp) 5 | 6 | add_library(lavos_shell_glfw ${SOURCE_FILES}) 7 | target_include_directories(lavos_shell_glfw PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include") 8 | target_link_libraries(lavos_shell_glfw PUBLIC lavos) 9 | 10 | find_package(glfw3 3.3 REQUIRED) 11 | target_link_libraries(lavos_shell_glfw PUBLIC glfw) -------------------------------------------------------------------------------- /demos/qt_shell/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 3 | set(CMAKE_AUTOMOC ON) 4 | set(CMAKE_AUTOUIC ON) 5 | set(CMAKE_AUTORCC ON) 6 | find_package(Qt5 5.10 COMPONENTS Core Gui Widgets REQUIRED) 7 | 8 | set(SOURCE_FILES 9 | main.cpp 10 | lavos_renderer.cpp 11 | lavos_renderer.h) 12 | 13 | add_executable(qt_shell ${SOURCE_FILES}) 14 | target_link_libraries(qt_shell 15 | Qt5::Core Qt5::Gui Qt5::Widgets 16 | lavos_shell_qt 17 | lavos) -------------------------------------------------------------------------------- /android/gltf/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /lavos/src/buffer.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "lavos/buffer.h" 3 | #include "lavos/engine.h" 4 | 5 | lavos::Buffer::~Buffer() 6 | { 7 | UnMap(); 8 | engine->DestroyBuffer(buffer, allocation); 9 | } 10 | 11 | void *lavos::Buffer::Map() 12 | { 13 | if(!map) 14 | map = engine->MapMemory(allocation); 15 | 16 | return map; 17 | } 18 | 19 | void lavos::Buffer::UnMap() 20 | { 21 | if(!map) 22 | return; 23 | engine->UnmapMemory(allocation); 24 | map = nullptr; 25 | } 26 | -------------------------------------------------------------------------------- /demos/qt_qvulkanwindow/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 3 | set(CMAKE_AUTOMOC ON) 4 | set(CMAKE_AUTOUIC ON) 5 | set(CMAKE_AUTORCC ON) 6 | find_package(Qt5 5.10 COMPONENTS Core Gui Widgets REQUIRED) 7 | 8 | set(SOURCE_FILES 9 | main.cpp 10 | mainwindow.cpp 11 | mainwindow.h) 12 | 13 | add_executable(qt_qvulkanwindow ${SOURCE_FILES}) 14 | target_link_libraries(qt_qvulkanwindow 15 | Qt5::Core Qt5::Gui Qt5::Widgets 16 | lavos_shell_qt 17 | lavos) -------------------------------------------------------------------------------- /demos/point_cloud/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | find_package(PCL 1.3 REQUIRED COMPONENTS common io) 3 | include_directories(${PCL_INCLUDE_DIRS}) 4 | link_directories(${PCL_LIBRARY_DIRS}) 5 | add_definitions(${PCL_DEFINITIONS}) 6 | 7 | set(SOURCE_FILES 8 | point_cloud.cpp) 9 | 10 | add_executable(point_cloud ${SOURCE_FILES}) 11 | target_link_libraries(point_cloud 12 | ${PCL_COMMON_LIBRARIES} 13 | ${PCL_IO_LIBRARIES} 14 | lavos 15 | lavos_shell_glfw 16 | glfw 17 | ${Vulkan_LIBRARIES}) -------------------------------------------------------------------------------- /lavos/include/lavos/component/component.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef LAVOS_COMPONENT_H 3 | #define LAVOS_COMPONENT_H 4 | 5 | namespace lavos 6 | { 7 | 8 | class Node; 9 | 10 | class Component 11 | { 12 | friend class Node; 13 | 14 | private: 15 | Node *node = nullptr; 16 | 17 | public: 18 | virtual ~Component() {} 19 | 20 | Node *GetNode() const { return node; } 21 | 22 | virtual void Update(float delta_time) {} 23 | }; 24 | 25 | } 26 | 27 | 28 | #endif //VULKAN_COMPONENT_H 29 | -------------------------------------------------------------------------------- /lavos/include/lavos/log.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef LAVOS_LOG_H 3 | #define LAVOS_LOG_H 4 | 5 | namespace lavos 6 | { 7 | 8 | enum class LogLevel { Debug, Info, Warning, Error }; 9 | 10 | void LogF(LogLevel level, const char *file, int line, const char *function, const char *fmt, ...); 11 | 12 | } 13 | 14 | #define LAVOS_LOGF(level, fmt, ...) { lavos::LogF((level), __FILE__, __LINE__, __func__, fmt, __VA_ARGS__); } 15 | #define LAVOS_LOG(level, str) { LAVOS_LOGF((level), "%s", str); } 16 | 17 | #endif //LAVOS_LOG_H 18 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: [push] 3 | 4 | jobs: 5 | build: 6 | name: CI 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: actions/checkout@v2 10 | - name: Checkout submodules 11 | run: | 12 | git submodule init 13 | git submodule update 14 | - name: Docker Build 15 | run: docker build -t lavos . 16 | - name: Build Lavos 17 | run: docker run --rm -v "`pwd`:/build" -t lavos /bin/bash -c "cd /build && ./ci-script" 18 | 19 | -------------------------------------------------------------------------------- /lavos/src/thirdparty_impl.cpp: -------------------------------------------------------------------------------- 1 | 2 | #ifdef LAVOS_IMPLEMENT_STB_IMAGE 3 | # define STB_IMAGE_IMPLEMENTATION 4 | # include "../../thirdparty/stb_image.h" 5 | # undef STB_IMAGE_IMPLEMENTATION 6 | #endif 7 | 8 | #ifdef LAVOS_IMPLEMENT_TINYGLTF 9 | # define TINYGLTF_IMPLEMENTATION 10 | # include "../../thirdparty/tiny_gltf.h" 11 | # undef TINYGLTF_IMPLEMENTATION 12 | #endif 13 | 14 | #ifdef LAVOS_IMPLEMENT_VMA 15 | # define VMA_IMPLEMENTATION 16 | # include "vk_mem_alloc.h" 17 | # undef VMA_IMPLEMENTATION 18 | #endif 19 | -------------------------------------------------------------------------------- /lavos/src/light_collection.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "lavos/light_collection.h" 3 | #include "lavos/scene.h" 4 | #include "lavos/component/directional_light.h" 5 | #include "lavos/component/spot_light.h" 6 | 7 | using namespace lavos; 8 | 9 | LightCollection LightCollection::EverythingInScene(Scene *scene) 10 | { 11 | LightCollection ret; 12 | ret.dir_light = scene->GetRootNode()->GetComponentInChildren(); 13 | ret.spot_lights = scene->GetRootNode()->GetComponentsInChildren(); 14 | return std::move(ret); 15 | } -------------------------------------------------------------------------------- /lavos/include/lavos/sub_renderer.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef LAVOS_SUB_RENDERER_H 3 | #define LAVOS_SUB_RENDERER_H 4 | 5 | namespace lavos 6 | { 7 | 8 | class Engine; 9 | class Material; 10 | 11 | class SubRenderer 12 | { 13 | protected: 14 | Engine * const engine; 15 | 16 | public: 17 | explicit SubRenderer(Engine *engine); 18 | virtual ~SubRenderer() = default; 19 | 20 | virtual void AddMaterial(Material *material) {} 21 | virtual void RemoveMaterial(Material *material) {} 22 | }; 23 | 24 | } 25 | 26 | #endif //LAVOS_SUB_RENDERER_H 27 | -------------------------------------------------------------------------------- /demos/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_subdirectory(gltf) 3 | add_subdirectory(firstperson) 4 | add_subdirectory(2d) 5 | add_subdirectory(room) 6 | 7 | if(LAVOS_BUILD_POINT_CLOUD_DEMO) 8 | add_subdirectory(point_cloud) 9 | endif() 10 | 11 | if(LAVOS_BUILD_QT_DEMOS) 12 | if(NOT LAVOS_BUILD_SHELL_QT) 13 | message(FATAL_ERROR "Lavos Qt Shell is required for the Qt demos. Either enable it using -DLAVOS_BUILD_SHELL_QT=ON or disable building the Qt demos.") 14 | endif() 15 | 16 | add_subdirectory(qt_qvulkanwindow) 17 | add_subdirectory(qt_shell) 18 | endif() -------------------------------------------------------------------------------- /lavos/cmake/ResourceGenerator_header.h.in: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _@RESOURCE_GENERATOR_INCLUDE_GUARD@_H 3 | #define _@RESOURCE_GENERATOR_INCLUDE_GUARD@_H 4 | 5 | namespace lavos 6 | { 7 | 8 | const @RESOURCE_GENERATOR_TYPE@ *@RESOURCE_GENERATOR_FUNCTION_PREFIX@_get(const char *filename, size_t *size); 9 | inline const @RESOURCE_GENERATOR_TYPE@ *@RESOURCE_GENERATOR_FUNCTION_PREFIX@_get(const char *filename) 10 | { 11 | return @RESOURCE_GENERATOR_FUNCTION_PREFIX@_get(filename, 0); 12 | } 13 | 14 | } 15 | 16 | #endif // _@RESOURCE_GENERATOR_INCLUDE_GUARD@_H 17 | -------------------------------------------------------------------------------- /shell/qt/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 3 | set(CMAKE_AUTOMOC ON) 4 | set(CMAKE_AUTOUIC OFF) 5 | set(CMAKE_AUTORCC OFF) 6 | find_package(Qt5 5.10 COMPONENTS Core Gui REQUIRED) 7 | 8 | set(SOURCE_FILES 9 | include/lavos_window.h 10 | src/lavos_window.cpp 11 | include/platform.h 12 | src/platform.cpp) 13 | 14 | add_library(lavos_shell_qt ${SOURCE_FILES}) 15 | target_include_directories(lavos_shell_qt PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include") 16 | target_link_libraries(lavos_shell_qt 17 | Qt5::Core Qt5::Gui 18 | lavos) -------------------------------------------------------------------------------- /android/common/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | add_library(demo_android SHARED 4 | android_common.cpp 5 | android_common.h 6 | ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) 7 | 8 | target_include_directories(demo_android PRIVATE 9 | ${ANDROID_NDK}/sources/android/native_app_glue 10 | ${ANDROID_NDK}/sources/third_party/shaderc/include) 11 | 12 | target_link_libraries(demo_android 13 | android 14 | log 15 | vulkan 16 | ${MODULE_NAME} 17 | demo_common) 18 | -------------------------------------------------------------------------------- /cmake/FindVulkanHPP.cmake: -------------------------------------------------------------------------------- 1 | # FindVulkanHPP 2 | # ---------- 3 | # 4 | # This module defines the following variables: 5 | # 6 | # VulkanHPP_FOUND - True if vulkan.hpp was found 7 | # VulkanHPP_INCLUDE_DIRS - include directories for vulkan.hpp 8 | 9 | find_path(VulkanHPP_INCLUDE_DIRS 10 | NAMES vulkan/vulkan.hpp 11 | PATHS 12 | "$ENV{VULKAN_SDK}/Include" 13 | "${VULKAN_INCLUDE_DIRS}") 14 | 15 | include(FindPackageHandleStandardArgs) 16 | find_package_handle_standard_args(VulkanHPP DEFAULT_MSG VulkanHPP_INCLUDE_DIRS) 17 | -------------------------------------------------------------------------------- /lavos/glsl/material/lighting_phong.glsl: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _MATERIAL_LIGHTING_PHONG_GLSL 3 | #define _MATERIAL_LIGHTING_PHONG_GLSL 4 | 5 | struct PhongMaterialParameters 6 | { 7 | vec4 base_color; 8 | float specular_exponent; 9 | }; 10 | 11 | float LightingPhong(vec3 normal, vec3 light_dir, vec3 cam_dir, float specular_exponent) 12 | { 13 | float lambert = max(0.0, dot(light_dir, normal)); 14 | 15 | float specular = max(0.0, dot(reflect(-light_dir, normal), cam_dir)); 16 | specular = pow(specular, specular_exponent); 17 | 18 | return lambert + specular; 19 | } 20 | 21 | #endif -------------------------------------------------------------------------------- /lavos/include/lavos/light_collection.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef LAVOS_LIGHT_COLLECTION_H 3 | #define LAVOS_LIGHT_COLLECTION_H 4 | 5 | #include 6 | 7 | namespace lavos 8 | { 9 | 10 | class DirectionalLight; 11 | class SpotLight; 12 | class Scene; 13 | 14 | /** 15 | * Accumulates all the lights used for rendering, 16 | * could also be local to a cluster for example. 17 | */ 18 | struct LightCollection 19 | { 20 | DirectionalLight *dir_light; 21 | std::vector spot_lights; 22 | 23 | static LightCollection EverythingInScene(Scene *scene); 24 | }; 25 | 26 | } 27 | 28 | #endif //LAVOS_LIGHT_COLLECTION_H 29 | -------------------------------------------------------------------------------- /lavos/glsl/common_glsl_cpp.h: -------------------------------------------------------------------------------- 1 | // Common defines for both GLSL and C++ 2 | // must compile under both 3 | 4 | #ifndef LAVOS_COMMON_GLSL_CPP_H 5 | #define LAVOS_COMMON_GLSL_CPP_H 6 | 7 | #define DESCRIPTOR_SET_INDEX_COMMON 0 8 | #define DESCRIPTOR_SET_INDEX_MATERIAL 1 9 | 10 | #define MAX_SPOT_LIGHTS_COUNT 16 11 | 12 | #define DESCRIPTOR_SET_COMMON_BINDING_MATRIX_BUFFER 0 13 | #define DESCRIPTOR_SET_COMMON_BINDING_LIGHTING_BUFFER 1 14 | #define DESCRIPTOR_SET_COMMON_BINDING_CAMERA_BUFFER 2 15 | #define DESCRIPTOR_SET_COMMON_BINDING_SPOT_LIGHT_SHADOW_TEX 3 16 | 17 | #define SHADOW_MSM 1 18 | 19 | #endif //LAVOS_COMMON_GLSL_CPP_H 20 | -------------------------------------------------------------------------------- /lavos/cmake/ResourceGenerator_source.cpp.in: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include "@RESOURCE_GENERATOR_HEADER_FILE_RELATIVE@" 4 | 5 | @RESOURCE_GENERATOR_RESOURCES_SOURCE@ 6 | 7 | static const unsigned int resources_count = @RESOURCE_GENERATOR_RESOURCES_COUNT@; 8 | static const char *all_resources_names[] = {@RESOURCE_GENERATOR_RESOURCES_ALL_NAMES@}; 9 | static const @RESOURCE_GENERATOR_TYPE@ *all_resources[] = {@RESOURCE_GENERATOR_RESOURCES_ALL@}; 10 | 11 | const @RESOURCE_GENERATOR_TYPE@ *lavos::@RESOURCE_GENERATOR_FUNCTION_PREFIX@_get(const char *filename, size_t *size) 12 | { 13 | @RESOURCE_GENERATOR_GET_FUNCTION_SOURCE@ 14 | return 0; 15 | } -------------------------------------------------------------------------------- /lavos/include/lavos/component/directional_light.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef LAVOS_DIRECTIONAL_LIGHT_H 3 | #define LAVOS_DIRECTIONAL_LIGHT_H 4 | 5 | #include 6 | 7 | #include "component.h" 8 | 9 | namespace lavos 10 | { 11 | 12 | class DirectionalLight: public Component 13 | { 14 | private: 15 | glm::vec3 intensity; 16 | 17 | public: 18 | DirectionalLight(glm::vec3 intensity = glm::vec3(1.0f, 1.0f, 1.0f)); 19 | ~DirectionalLight(); 20 | 21 | glm::vec3 GetIntensity() const { return intensity; } 22 | void SetIntensity(const glm::vec3 &intensity) { this->intensity = intensity; } 23 | }; 24 | 25 | } 26 | 27 | #endif //VULKAN_DIRECTIONAL_LIGHT_COMPONENT_H 28 | -------------------------------------------------------------------------------- /lavos/include/lavos/component/fp_controller.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef LAVOS_FP_CAMERA_CONTROLLER_COMPONENT_H 3 | #define LAVOS_FP_CAMERA_CONTROLLER_COMPONENT_H 4 | 5 | #include "component.h" 6 | #include "transform_component.h" 7 | 8 | namespace lavos 9 | { 10 | 11 | class FirstPersonController : public Component 12 | { 13 | private: 14 | glm::vec2 rotation; 15 | glm::vec2 velocity; 16 | 17 | public: 18 | virtual void Update(float delta_time) override; 19 | 20 | void SetRotation(glm::vec2 rotation) { this->rotation = rotation; } 21 | void Rotate(glm::vec2 rot); 22 | void SetVelocity(glm::vec2 velocity); 23 | }; 24 | 25 | } 26 | 27 | #endif //VULKAN_FP_CAMERA_CONTROLLER_COMPONENT_H 28 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | 5 | repositories { 6 | google() 7 | jcenter() 8 | } 9 | dependencies { 10 | classpath 'com.android.tools.build:gradle:3.0.0-beta6' 11 | 12 | 13 | // NOTE: Do not place your application dependencies here; they belong 14 | // in the individual module build.gradle files 15 | } 16 | } 17 | 18 | 19 | allprojects { 20 | repositories { 21 | google() 22 | jcenter() 23 | } 24 | } 25 | 26 | task clean(type: Delete) { 27 | delete rootProject.buildDir 28 | } 29 | -------------------------------------------------------------------------------- /lavos/include/lavos/buffer.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef LAVOS_BUFFER_H 3 | #define LAVOS_BUFFER_H 4 | 5 | #include 6 | #include "vk_mem_alloc.h" 7 | 8 | namespace lavos 9 | { 10 | 11 | class Engine; 12 | 13 | class Buffer 14 | { 15 | private: 16 | Engine * const engine; 17 | 18 | vk::Buffer buffer; 19 | VmaAllocation allocation; 20 | void *map = nullptr; 21 | 22 | public: 23 | Buffer(Engine *engine, vk::Buffer buffer, VmaAllocation allocation) 24 | : engine(engine), buffer(buffer), allocation(allocation) {} 25 | 26 | ~Buffer(); 27 | 28 | vk::Buffer GetVkBuffer() { return buffer; } 29 | 30 | void *Map(); 31 | void UnMap(); 32 | }; 33 | 34 | } 35 | 36 | #endif //VULKAN_BUFFER_H 37 | -------------------------------------------------------------------------------- /lavos/src/component/fp_controller.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "lavos/component/fp_controller.h" 3 | 4 | using namespace lavos; 5 | 6 | void FirstPersonController::Update(float delta_time) 7 | { 8 | TransformComp *transform = GetNode()->GetTransformComp(); 9 | 10 | transform->rotation = glm::quat(glm::vec3(-rotation.y, -rotation.x, 0.0f)); 11 | 12 | glm::mat4 mat = transform->GetMatrix(); 13 | transform->translation += glm::vec3(mat * glm::vec4(velocity.x * delta_time, 0.0f, -velocity.y * delta_time, 0.0f)); 14 | } 15 | 16 | void FirstPersonController::Rotate(glm::vec2 rot) 17 | { 18 | rotation += rot; 19 | } 20 | 21 | void FirstPersonController::SetVelocity(glm::vec2 velocity) 22 | { 23 | this->velocity = velocity; 24 | } 25 | -------------------------------------------------------------------------------- /lavos/src/component/mesh_component.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "lavos/component/mesh_component.h" 3 | 4 | lavos::MeshComp::MeshComp(lavos::Mesh *mesh) 5 | { 6 | SetMesh(mesh); 7 | } 8 | 9 | void lavos::MeshComp::BindBuffers(vk::CommandBuffer command_buffer) 10 | { 11 | command_buffer.bindVertexBuffers(0, { mesh->vertex_buffer->GetVkBuffer() }, { 0 }); 12 | command_buffer.bindIndexBuffer(mesh->index_buffer->GetVkBuffer(), 0, vk::IndexType::eUint16); 13 | } 14 | 15 | unsigned int lavos::MeshComp::GetPrimitivesCount() 16 | { 17 | return static_cast(mesh->primitives.size()); 18 | } 19 | 20 | lavos::Renderable::Primitive *lavos::MeshComp::GetPrimitive(unsigned int i) 21 | { 22 | return &mesh->primitives[i]; 23 | } 24 | -------------------------------------------------------------------------------- /lavos/src/component/spot_light.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "lavos/component/spot_light.h" 3 | #include "lavos/spot_light_shadow.h" 4 | #include "lavos/node.h" 5 | #include "lavos/component/transform_component.h" 6 | 7 | using namespace lavos; 8 | 9 | SpotLight::SpotLight(glm::vec3 intensity, float angle) 10 | : intensity(intensity), angle(angle) 11 | { 12 | } 13 | 14 | SpotLight::~SpotLight() 15 | { 16 | DestroyShadow(); 17 | } 18 | 19 | void SpotLight::InitShadow(Engine *engine, SpotLightShadowRenderer *renderer, float near_clip, float far_clip) 20 | { 21 | DestroyShadow(); 22 | shadow = new SpotLightShadow(engine, this, renderer, near_clip, far_clip); 23 | } 24 | 25 | void SpotLight::DestroyShadow() 26 | { 27 | delete shadow; 28 | } 29 | -------------------------------------------------------------------------------- /lavos/include/lavos/scene.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef LAVOS_SCENE_H 3 | #define LAVOS_SCENE_H 4 | 5 | #include "glm_config.h" 6 | #include 7 | 8 | #include "node.h" 9 | 10 | namespace lavos 11 | { 12 | 13 | class Scene 14 | { 15 | private: 16 | Node root_node; 17 | 18 | glm::vec3 ambient_light_intensity; 19 | 20 | public: 21 | Scene(); 22 | ~Scene(); 23 | 24 | Node *GetRootNode() { return &root_node; } 25 | 26 | glm::vec3 GetAmbientLightIntensity() const { return ambient_light_intensity; } 27 | void SetAmbientLightIntensity(glm::vec3 intensity) { ambient_light_intensity = intensity; } 28 | 29 | void Update(float delta_time) { root_node.Update(delta_time); } 30 | }; 31 | 32 | 33 | } 34 | 35 | #endif //VULKAN_SCENE_H 36 | -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | org.gradle.jvmargs=-Xmx1536m 13 | 14 | # When configured, Gradle will run in incubating parallel mode. 15 | # This option should only be used with decoupled projects. More details, visit 16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 17 | # org.gradle.parallel=true 18 | -------------------------------------------------------------------------------- /lavos/include/lavos/render_config.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef LAVOS_RENDER_CONFIG_H 3 | #define LAVOS_RENDER_CONFIG_H 4 | 5 | #include "material/material.h" 6 | 7 | namespace lavos 8 | { 9 | 10 | class RenderConfigBuilder; 11 | 12 | class RenderConfig 13 | { 14 | friend class RenderConfigBuilder; 15 | 16 | private: 17 | std::vector material_render_modes; 18 | 19 | public: 20 | const std::vector &GetMaterialRenderModes() const { return material_render_modes; } 21 | }; 22 | 23 | class RenderConfigBuilder 24 | { 25 | private: 26 | bool shadow_enabled = false; 27 | 28 | public: 29 | RenderConfigBuilder &SetShadowEnabled(bool enabled) { shadow_enabled = enabled; return *this; } 30 | 31 | RenderConfig Build(); 32 | }; 33 | 34 | } 35 | 36 | #endif //LAVOS_RENDER_CONFIG_H 37 | -------------------------------------------------------------------------------- /android/common/android_common.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef ANDROID_COMMON_H 3 | #define ANDROID_COMMON_H 4 | 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | #define LOG_TAG "native-activity" 12 | 13 | #define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)) 14 | #define LOGE(...) ((void)__android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)) 15 | 16 | void AndroidSetApp(android_app *_app); 17 | ANativeWindow *AndroidGetApplicationWindow(); 18 | void AndroidGetWindowSize(int32_t *width, int32_t *height); 19 | 20 | std::vector AndroidReadSPIRVShader(const std::string shader); 21 | std::vector AndroidReadAssetBinary(const std::string filename); 22 | 23 | void sample_main(); 24 | 25 | #endif //ANDROID_COMMON_H 26 | -------------------------------------------------------------------------------- /lavos/include/lavos/component/mesh_component.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef LAVOS_MESH_COMPONENT_H 3 | #define LAVOS_MESH_COMPONENT_H 4 | 5 | #include "component.h" 6 | #include "../mesh.h" 7 | #include "../renderable.h" 8 | 9 | namespace lavos 10 | { 11 | 12 | class MeshComp: public Component, public Renderable 13 | { 14 | private: 15 | Mesh *mesh; 16 | 17 | public: 18 | MeshComp(Mesh *mesh = nullptr); 19 | 20 | void SetMesh(Mesh *mesh) { this->mesh = mesh; } 21 | Mesh *GetMesh() const { return mesh; } 22 | 23 | bool GetCurrentlyRenderable() const override { return mesh != nullptr; } 24 | 25 | void BindBuffers(vk::CommandBuffer command_buffer) override; 26 | unsigned int GetPrimitivesCount() override; 27 | Primitive *GetPrimitive(unsigned int i) override; 28 | }; 29 | 30 | } 31 | 32 | #endif //VULKAN_MESH_COMPONENT_H 33 | -------------------------------------------------------------------------------- /shell/qt/src/platform.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "platform.h" 3 | 4 | #include 5 | 6 | std::set lavos::shell::qt::GetSurfaceExtensionsForPlatform() 7 | { 8 | // Qt already has all this, but it is not publicly exposed :( 9 | 10 | const auto platform = QGuiApplication::platformName(); 11 | 12 | if(platform == "xcb") 13 | { 14 | return { 15 | "VK_KHR_surface", 16 | "VK_KHR_xcb_surface" 17 | }; 18 | } 19 | else if(platform == "wayland") 20 | { 21 | return { 22 | "VK_KHR_surface", 23 | "VK_KHR_wayland_surface" 24 | }; 25 | } 26 | else if(platform == "windows") 27 | { 28 | return { 29 | "VK_KHR_surface", 30 | "VK_KHR_win32_surface" 31 | }; 32 | } 33 | else if(platform == "cocoa") 34 | { 35 | return { 36 | "VK_KHR_surface", 37 | "VK_MVK_macos_surface" 38 | }; 39 | } 40 | } -------------------------------------------------------------------------------- /lavos/glsl/material/shadow.vf.shader: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | #include "common.glsl" 4 | 5 | #ifdef SHADER_VERT 6 | 7 | #define COMMON_VERT_MATRIX_COMPACT 8 | #include "common_vert.glsl" 9 | 10 | #if SHADOW_MSM 11 | layout(location = 0) out float z_out; 12 | #endif 13 | 14 | out gl_PerVertex 15 | { 16 | vec4 gl_Position; 17 | }; 18 | 19 | void main() 20 | { 21 | vec4 pos = CalculateVertexPosition(); 22 | #if SHADOW_MSM 23 | z_out = pos.z; 24 | #endif 25 | gl_Position = pos; 26 | } 27 | 28 | // ------------------------------------------------- 29 | #elif SHADER_FRAG 30 | 31 | #if SHADOW_MSM 32 | layout(location = 0) in float z_in; 33 | layout(location = 0) out vec4 shadow_out; 34 | #endif 35 | 36 | void main() 37 | { 38 | #if SHADOW_MSM 39 | float z = z_in; 40 | shadow_out = vec4(z, z*z, z*z*z, z*z*z*z); 41 | #endif 42 | } 43 | 44 | #endif -------------------------------------------------------------------------------- /lavos/glsl/material/unlit.vf.shader: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | #if SHADER_VERT 4 | 5 | #include "common_vert.glsl" 6 | 7 | out gl_PerVertex 8 | { 9 | vec4 gl_Position; 10 | }; 11 | 12 | layout(location = 1) out vec2 uv_out; 13 | 14 | void main() 15 | { 16 | gl_Position = CalculateVertexPosition(); 17 | 18 | uv_out = uv_in; 19 | } 20 | 21 | #elif SHADER_FRAG 22 | 23 | #include "common_frag.glsl" 24 | 25 | layout(set = DESCRIPTOR_SET_INDEX_MATERIAL, binding = 0, std140) uniform MaterialBuffer 26 | { 27 | vec3 color_factor; 28 | } material_uni; 29 | 30 | layout(set = DESCRIPTOR_SET_INDEX_MATERIAL, binding = 1) uniform sampler2D tex_uni; 31 | 32 | layout(location = 1) in vec2 uv_in; 33 | 34 | void main() 35 | { 36 | vec4 tex_color = texture(tex_uni, uv_in); 37 | out_color = vec4(tex_color.rgb * material_uni.color_factor, tex_color.a); 38 | } 39 | 40 | #endif -------------------------------------------------------------------------------- /demos/qt_shell/lavos_renderer.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef LAVOS_LAVOS_RENDERER_H 3 | #define LAVOS_LAVOS_RENDERER_H 4 | 5 | #include 6 | 7 | class LavosWindowRenderer : public lavos::shell::qt::LavosWindow::Renderer 8 | { 9 | private: 10 | lavos::Engine *engine = nullptr; 11 | 12 | lavos::RenderConfig render_config; 13 | 14 | lavos::PhongMaterial *material = nullptr; 15 | lavos::Scene *scene = nullptr; 16 | lavos::Camera *camera = nullptr; 17 | 18 | lavos::Renderer *renderer = nullptr; 19 | 20 | lavos::AssetContainer *asset_container = nullptr; 21 | 22 | public: 23 | LavosWindowRenderer(lavos::Engine *engine); 24 | ~LavosWindowRenderer(); 25 | 26 | void InitializeSwapchainResources(lavos::shell::qt::LavosWindow *window) override; 27 | void ReleaseSwapchainResources() override; 28 | 29 | void Render(lavos::shell::qt::LavosWindow *window); 30 | }; 31 | 32 | #endif //LAVOS_LAVOS_RENDERER_H 33 | -------------------------------------------------------------------------------- /lavos/include/lavos/asset_container.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef LAVOS_ASSET_CONTAINER_H 3 | #define LAVOS_ASSET_CONTAINER_H 4 | 5 | #include 6 | #include 7 | 8 | #include "material/material_instance.h" 9 | #include "mesh.h" 10 | #include "scene.h" 11 | 12 | namespace lavos 13 | { 14 | 15 | class AssetContainer 16 | { 17 | public: 18 | Engine * const engine; 19 | const RenderConfig render_config; 20 | 21 | vk::DescriptorPool descriptor_pool; 22 | 23 | std::vector material_instances; 24 | std::vector meshes; 25 | std::vector scenes; 26 | 27 | AssetContainer(Engine *engine, const RenderConfig &render_config); 28 | ~AssetContainer(); 29 | 30 | const RenderConfig &GetRenderConfig() { return render_config; } 31 | 32 | static AssetContainer *LoadFromGLTF(Engine *engine, const RenderConfig &render_config, Material *material, std::string filename); 33 | }; 34 | 35 | } 36 | 37 | #endif //VULKAN_GLTF_LOADER_H 38 | -------------------------------------------------------------------------------- /android/gltf/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /home/florian/android/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | 19 | # Uncomment this to preserve the line number information for 20 | # debugging stack traces. 21 | #-keepattributes SourceFile,LineNumberTable 22 | 23 | # If you keep the line number information, uncomment this to 24 | # hide the original source file name. 25 | #-renamesourcefileattribute SourceFile 26 | -------------------------------------------------------------------------------- /demos/qt_qvulkanwindow/main.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | #include "mainwindow.h" 9 | 10 | int main(int argc, char **argv) 11 | { 12 | QApplication app(argc, argv); 13 | 14 | lavos::Engine::CreateInfo engine_create_info; 15 | engine_create_info.app_info = "Qt Demo"; 16 | 17 | engine_create_info.enable_validation_layers = true; 18 | engine_create_info.enable_anisotropy = false; 19 | 20 | engine_create_info.required_instance_extensions = lavos::shell::qt::GetSurfaceExtensionsForPlatform(); 21 | 22 | lavos::Engine *engine = new lavos::Engine(engine_create_info); 23 | 24 | QVulkanInstance inst; 25 | inst.setVkInstance(engine->GetVkInstance()); 26 | 27 | if(!inst.create()) 28 | { 29 | qFatal("Failed to create vulkan instance: %d", inst.errorCode()); 30 | } 31 | 32 | MainWindow window(engine); 33 | window.setVulkanInstance(&inst); 34 | window.setWidth(640); 35 | window.setHeight(480); 36 | window.show(); 37 | 38 | return app.exec(); 39 | } -------------------------------------------------------------------------------- /lavos/include/lavos/texture.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef LAVOS_TEXTURE_H 3 | #define LAVOS_TEXTURE_H 4 | 5 | #include "image.h" 6 | 7 | namespace lavos 8 | { 9 | 10 | class Engine; 11 | 12 | class Texture 13 | { 14 | public: 15 | Image image; 16 | vk::ImageView image_view; 17 | vk::Sampler sampler; 18 | 19 | Texture(std::nullptr_t = nullptr) 20 | : image(), image_view(nullptr), sampler(nullptr) {} 21 | 22 | Texture(Image image, vk::ImageView image_view, vk::Sampler sampler) 23 | : image(image), image_view(image_view), sampler(sampler) {} 24 | 25 | 26 | static Texture CreateColor(Engine *engine, vk::Format format, glm::vec4 color); 27 | 28 | 29 | bool operator==(Texture const &rhs) const 30 | { 31 | return image == rhs.image 32 | && image_view == rhs.image_view 33 | && sampler == rhs.sampler; 34 | } 35 | 36 | bool operator!=(Texture const &rhs) const 37 | { 38 | return image != rhs.image 39 | || image_view != rhs.image_view 40 | || sampler != rhs.sampler; 41 | } 42 | }; 43 | 44 | } 45 | 46 | #endif //VULKAN_TEXTURE_H 47 | -------------------------------------------------------------------------------- /lavos/glsl/material/common_vert.glsl: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _MATERIAL_COMMON_VERT_H 3 | #define _MATERIAL_COMMON_VERT_H 4 | 5 | #include "common.glsl" 6 | 7 | layout(set = DESCRIPTOR_SET_INDEX_COMMON, binding = DESCRIPTOR_SET_COMMON_BINDING_MATRIX_BUFFER) uniform MatrixBuffer 8 | { 9 | #ifdef COMMON_VERT_MATRIX_COMPACT 10 | mat4 modelview_projection; 11 | #else 12 | mat4 modelview; 13 | mat4 projection; 14 | #endif 15 | } matrix_uni; 16 | 17 | layout(push_constant) uniform TransformPushConstant 18 | { 19 | mat4 transform; 20 | } transform_push_constant; 21 | 22 | layout(location = 0) in vec3 position_in; 23 | layout(location = 1) in vec2 uv_in; 24 | layout(location = 2) in vec3 normal_in; 25 | layout(location = 3) in vec3 tang_in; 26 | layout(location = 4) in vec3 bitang_in; 27 | 28 | vec4 CalculateVertexPosition() 29 | { 30 | #ifdef COMMON_VERT_MATRIX_COMPACT 31 | mat4 mvp = matrix_uni.modelview_projection; 32 | #else 33 | mat4 mvp = matrix_uni.projection * matrix_uni.modelview; 34 | #endif 35 | return mvp 36 | * transform_push_constant.transform 37 | * vec4(position_in, 1.0); 38 | } 39 | 40 | #endif -------------------------------------------------------------------------------- /lavos/src/log.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "lavos/log.h" 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace lavos; 8 | 9 | 10 | void lavos::LogF(LogLevel level, const char *file, int line, const char *function, const char *fmt, ...) 11 | { 12 | const char *level_str = nullptr; 13 | const char *ansi_str = nullptr; 14 | switch(level) 15 | { 16 | case LogLevel::Debug: 17 | level_str = "D"; 18 | ansi_str = "\x1b[36m"; 19 | break; 20 | case LogLevel::Info: 21 | level_str = "I"; 22 | ansi_str = ""; 23 | break; 24 | case LogLevel::Warning: 25 | level_str = "W"; 26 | ansi_str = "\x1b[33m"; 27 | break; 28 | case LogLevel::Error: 29 | level_str = "E"; 30 | ansi_str = "\x1b[31m"; 31 | break; 32 | } 33 | 34 | const char *filename = strrchr(file, '/'); 35 | if(!filename) 36 | filename = file; 37 | else 38 | filename++; 39 | 40 | printf("%s[%s %16.16s:%-4d - %-20.20s] ", ansi_str, level_str, filename, line, function); 41 | va_list ap; 42 | va_start (ap, fmt); 43 | vprintf(fmt, ap); 44 | va_end (ap); 45 | printf("\x1b[0m\n"); 46 | } -------------------------------------------------------------------------------- /android/gltf/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 13 | 14 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /lavos/glsl/material/point_cloud.vf.shader: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | #if SHADER_VERT 4 | 5 | #include "common.glsl" 6 | 7 | layout(set = DESCRIPTOR_SET_INDEX_COMMON, binding = 0) uniform MatrixBuffer 8 | { 9 | mat4 modelview; 10 | mat4 projection; 11 | } matrix_uni; 12 | 13 | layout(push_constant) uniform TransformPushConstant 14 | { 15 | mat4 transform; 16 | } transform_push_constant; 17 | 18 | layout(location = 0) in vec3 position_in; 19 | 20 | vec4 CalculateVertexPosition() 21 | { 22 | return matrix_uni.projection 23 | * matrix_uni.modelview 24 | * transform_push_constant.transform 25 | * vec4(position_in, 1.0); 26 | } 27 | 28 | #include "common_camera.glsl" 29 | 30 | out gl_PerVertex 31 | { 32 | vec4 gl_Position; 33 | float gl_PointSize; 34 | }; 35 | 36 | layout(location = 1) out vec3 color_out; 37 | 38 | void main() 39 | { 40 | gl_Position = CalculateVertexPosition(); 41 | gl_PointSize = 1.0f; 42 | color_out = vec3(1.0); 43 | } 44 | 45 | #elif SHADER_FRAG 46 | 47 | #include "common_frag.glsl" 48 | 49 | layout(location = 1) in vec3 color_in; 50 | 51 | void main() 52 | { 53 | out_color = vec4(color_in, 1.0); 54 | } 55 | 56 | #endif -------------------------------------------------------------------------------- /lavos/include/lavos/mesh.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef LAVOS_MESH_H 3 | #define LAVOS_MESH_H 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include "vertex.h" 10 | #include "buffer.h" 11 | #include "renderable.h" 12 | #include "material/material_instance.h" 13 | 14 | namespace lavos 15 | { 16 | 17 | class Mesh 18 | { 19 | private: 20 | Engine * const engine; 21 | 22 | public: 23 | struct Primitive: public Renderable::Primitive 24 | { 25 | MaterialInstance *material_instance; 26 | uint32_t indices_count; 27 | uint32_t indices_offset; 28 | 29 | MaterialInstance *GetMaterialInstance() override { return material_instance; } 30 | void Draw(vk::CommandBuffer command_buffer) override; 31 | }; 32 | 33 | std::vector vertices; 34 | std::vector indices; 35 | std::vector primitives; 36 | 37 | lavos::Buffer *vertex_buffer = nullptr; 38 | lavos::Buffer *index_buffer = nullptr; 39 | 40 | Mesh(Engine *engine); 41 | ~Mesh(); 42 | 43 | void CreateVertexBuffer(); 44 | void CreateIndexBuffer(); 45 | void CreateBuffers(); 46 | }; 47 | 48 | } 49 | 50 | #endif //VULKAN_MESH_H 51 | -------------------------------------------------------------------------------- /lavos/include/lavos/component/transform_component.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef LAVOS_TRANSFORM_COMPONENT_H 3 | #define LAVOS_TRANSFORM_COMPONENT_H 4 | 5 | #include "component.h" 6 | #include "../node.h" 7 | 8 | #include "../glm_config.h" 9 | #include 10 | #include 11 | #include 12 | 13 | namespace lavos 14 | { 15 | 16 | class TransformComp: public Component 17 | { 18 | public: 19 | glm::vec3 translation = glm::vec3(0.0f); 20 | glm::quat rotation; 21 | glm::vec3 scale = glm::vec3(1.0f); 22 | 23 | glm::mat4 GetMatrix() 24 | { 25 | return glm::scale(glm::translate(glm::mat4(1.0f), translation), scale) * glm::toMat4(rotation); 26 | } 27 | 28 | glm::mat4 GetMatrixWorld() 29 | { 30 | glm::mat4 m = GetMatrix(); 31 | 32 | Node *parent = GetNode()->GetParent(); 33 | if(parent == nullptr) 34 | return m; 35 | 36 | TransformComp *parent_transform = parent->GetTransformComp(); 37 | if(parent_transform == nullptr) 38 | return m; 39 | 40 | return parent_transform->GetMatrixWorld() * m; 41 | } 42 | 43 | void SetLookAt(glm::vec3 target, glm::vec3 up = glm::vec3(0.0f, 1.0f, 0.0f)); 44 | }; 45 | 46 | } 47 | 48 | #endif //VULKAN_TRANSFORM_COMPONENT_H 49 | -------------------------------------------------------------------------------- /lavos/src/shader_load.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "lavos/shader_load.h" 3 | 4 | #include 5 | #include 6 | 7 | #include "spirv_resources.h" 8 | 9 | using namespace lavos; 10 | 11 | #if defined(__ANDROID__) 12 | #include 13 | #endif 14 | 15 | static std::vector ReadFile(const std::string &filename) 16 | { 17 | std::ifstream file(filename, std::ios::ate | std::ios::binary); 18 | 19 | if(!file.is_open()) 20 | throw std::runtime_error("failed to open file!"); 21 | 22 | size_t size = static_cast(file.tellg()); 23 | std::vector buffer(size); 24 | 25 | file.seekg(0); 26 | file.read(buffer.data(), size); 27 | file.close(); 28 | 29 | return buffer; 30 | } 31 | 32 | /*std::vector engine::ReadSPIRVShader(const std::string shader) 33 | { 34 | #if defined(__ANDROID__) 35 | return AndroidReadSPIRVShader(shader); 36 | #else 37 | const char *shader_path = std::getenv("SHADER_PATH"); 38 | if(!shader_path) 39 | shader_path = "."; 40 | 41 | return ReadFile(std::string(shader_path) + "/" + shader + ".spv"); 42 | #endif 43 | }*/ 44 | 45 | 46 | const uint32_t *lavos::GetSPIRVShader(const std::string shader, size_t *size) 47 | { 48 | std::string filename = shader + ".spv"; 49 | return reinterpret_cast(spirv_resources_get(filename.c_str(), size)); 50 | } -------------------------------------------------------------------------------- /lavos/glsl/lib/msm.glsl: -------------------------------------------------------------------------------- 1 | 2 | // Peters C, Klein R. Moment shadow mapping 3 | 4 | #define MSM_BIAS 0.00003 5 | #define MSM_BLEEDING_REDUCTION 0.98 6 | 7 | float MSMShadow(vec4 smpl, float frag_z) 8 | { 9 | vec4 b = (1 - MSM_BIAS) * smpl + MSM_BIAS * vec4(0.5); 10 | float l32_d22 = -b[0] * b[1] + b[2]; 11 | float d22 = -b[0] * b[0] + b[1]; 12 | float sq_depth_variance = -b[1] * b[1] + b[3]; 13 | float d33_d22 = dot(vec2(sq_depth_variance, -l32_d22), vec2(d22, l32_d22)); 14 | float inv_d22 = 1.0f / d22; 15 | float l32 = l32_d22 * inv_d22; 16 | vec3 z; 17 | z[0] = frag_z; 18 | vec3 c = vec3(1.0f, z[0], z[0] * z[0]); 19 | c[1] -= b.x; 20 | c[2] -= b.y + l32 * c[1]; 21 | c[1] *= inv_d22; 22 | c[2] *= d22 / d33_d22; 23 | c[1] -= l32 * c[2]; 24 | c[0] -= dot(c.yz, b.xy); 25 | float inv_c2 = 1.0f / c[2]; 26 | float p = c[1] * inv_c2; 27 | float q = c[0] * inv_c2; 28 | float r = sqrt(p * p * 0.25f - q); 29 | z[1] = -p * 0.5f - r; 30 | z[2] = -p * 0.5f + r; 31 | vec4 sw = (z[2] < z[0]) 32 | ? vec4(z[1], z[0], 1.0f, 1.0f) 33 | : ((z[1] < z[0]) 34 | ? vec4(z[0], z[1], 0.0f, 1.0f) 35 | : vec4(0.0f, 0.0f, 0.0f, 0.0f)); 36 | float quot = (sw[0] * z[2] - b[0] * (sw[0] + z[2]) + b[1]) / ((z[2] - sw[1]) * (z[0] - z[1])); 37 | float shadow = sw[2] + sw[3] * quot; 38 | shadow /= MSM_BLEEDING_REDUCTION; 39 | return 1.0 - clamp(shadow, 0.0, 1.0); 40 | } -------------------------------------------------------------------------------- /lavos/include/lavos/component/spot_light.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef LAVOS_SPOT_LIGHT_H 3 | #define LAVOS_SPOT_LIGHT_H 4 | 5 | #include "../glm_config.h" 6 | #include 7 | #include 8 | #include 9 | 10 | #include "component.h" 11 | 12 | namespace lavos 13 | { 14 | 15 | class Engine; 16 | class SpotLightShadow; 17 | class SpotLightShadowRenderer; 18 | 19 | class SpotLight: public Component 20 | { 21 | private: 22 | glm::vec3 intensity; 23 | float angle; 24 | 25 | SpotLightShadow *shadow = nullptr; 26 | 27 | public: 28 | SpotLight(glm::vec3 intensity = glm::vec3(1.0f, 1.0f, 1.0f), float angle = glm::half_pi()); 29 | ~SpotLight(); 30 | 31 | /** 32 | * in radians 33 | */ 34 | float GetAngle() const { return angle; } 35 | 36 | /** 37 | * in radians 38 | */ 39 | void SetIntensity(float angle) { this->angle = angle; } 40 | 41 | glm::vec3 GetIntensity() const { return intensity; } 42 | void SetIntensity(const glm::vec3 &intensity) { this->intensity = intensity; } 43 | 44 | void InitShadow(Engine *engine, SpotLightShadowRenderer *renderer, float near_clip = 0.1f, float far_clip = 100.0f); 45 | void DestroyShadow(); 46 | SpotLightShadow *GetShadow() { return shadow; } 47 | }; 48 | 49 | } 50 | 51 | #endif //VULKAN_SPOT_LIGHT_COMPONENT_H 52 | -------------------------------------------------------------------------------- /demos/qt_shell/main.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | #include "lavos_renderer.h" 10 | 11 | int main(int argc, char **argv) 12 | { 13 | QApplication app(argc, argv); 14 | 15 | lavos::Engine::CreateInfo engine_create_info; 16 | engine_create_info.app_info = "Qt Demo"; 17 | 18 | engine_create_info.enable_validation_layers = true; 19 | engine_create_info.enable_anisotropy = true; 20 | 21 | engine_create_info.required_instance_extensions = lavos::shell::qt::GetSurfaceExtensionsForPlatform(); 22 | engine_create_info.required_device_extensions = { VK_KHR_SWAPCHAIN_EXTENSION_NAME }; 23 | 24 | lavos::Engine engine(engine_create_info); 25 | engine.InitializeWithPhysicalDeviceIndex(0); 26 | 27 | printf("Platform Name: %s\n", QGuiApplication::platformName().toLocal8Bit().constData()); 28 | 29 | QVulkanInstance inst; 30 | inst.setVkInstance(engine.GetVkInstance()); 31 | 32 | if(!inst.create()) 33 | { 34 | qFatal("Failed to create vulkan instance: %d", inst.errorCode()); 35 | } 36 | 37 | LavosWindowRenderer renderer(&engine); 38 | 39 | lavos::shell::qt::LavosWindow window(&engine, &renderer); 40 | window.setVulkanInstance(&inst); 41 | window.setWidth(640); 42 | window.setHeight(480); 43 | window.show(); 44 | 45 | return app.exec(); 46 | } -------------------------------------------------------------------------------- /lavos/include/lavos/material/unlit_material.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef LAVOS_UNLIT_MATERIAL_H 3 | #define LAVOS_UNLIT_MATERIAL_H 4 | 5 | #include "material.h" 6 | 7 | #include "../glm_config.h" 8 | #include 9 | 10 | namespace lavos 11 | { 12 | 13 | class UnlitMaterial: public Material 14 | { 15 | private: 16 | struct UniformBuffer 17 | { 18 | glm::vec3 color_factor; 19 | }; 20 | 21 | enum : Material::DescriptorSetId { 22 | DescriptorSetLayoutIdDefault 23 | }; 24 | 25 | void CreateDescriptorSetLayouts(); 26 | 27 | vk::ShaderModule vert_shader_module; 28 | vk::ShaderModule frag_shader_module; 29 | 30 | Texture texture_default_image; 31 | 32 | public: 33 | UnlitMaterial(Engine *engine); 34 | ~UnlitMaterial(); 35 | 36 | bool GetRenderModeSupport(RenderMode render_mode) const override 37 | { 38 | return render_mode == DefaultRenderMode::ColorForward; 39 | } 40 | 41 | std::vector GetShaderStageCreateInfos(RenderMode render_mode) const override; 42 | 43 | void WriteDescriptorSet(DescriptorSetId id, vk::DescriptorSet descriptor_set, MaterialInstance *instance) override; 44 | 45 | void *CreateInstanceData(InstanceDataId id) override; 46 | void DestroyInstanceData(InstanceDataId id, void *data) override; 47 | void UpdateInstanceData(InstanceDataId id, void *data, MaterialInstance *instance) override; 48 | }; 49 | 50 | } 51 | 52 | #endif //VULKAN_UNLIT_MATERIAL_H 53 | -------------------------------------------------------------------------------- /lavos/include/lavos/renderable.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef LAVOS_RENDERABLE_COMPONENT_H 3 | #define LAVOS_RENDERABLE_COMPONENT_H 4 | 5 | #include "component/component.h" 6 | #include "material/material_instance.h" 7 | 8 | namespace lavos 9 | { 10 | 11 | /** 12 | * Something that can be rendered by a {@link Renderer}. 13 | * 14 | * A Renderable consists of 0 or more {@link Primitive}s. 15 | * Each Primitive has exactly one {@link MaterialInstance} assigned to it and 16 | * describes a part of the Renderable. For a Mesh, for example, there would be 17 | * a Primitive for each part of the mesh that uses a different MaterialInstance. 18 | */ 19 | class Renderable 20 | { 21 | public: 22 | class Primitive 23 | { 24 | public: 25 | virtual ~Primitive() = default; 26 | 27 | virtual MaterialInstance *GetMaterialInstance() =0; 28 | virtual void Draw(vk::CommandBuffer command_buffer) =0; 29 | }; 30 | 31 | virtual ~Renderable() = default; 32 | 33 | /** 34 | * @return true iff the Renderable can currently be rendered. 35 | */ 36 | virtual bool GetCurrentlyRenderable() const { return true; } 37 | 38 | /** 39 | * Bind Vertex, Index, etc. buffers 40 | * @param command_buffer 41 | */ 42 | virtual void BindBuffers(vk::CommandBuffer command_buffer) =0; 43 | 44 | virtual unsigned int GetPrimitivesCount() =0; 45 | virtual Primitive *GetPrimitive(unsigned int i) =0; 46 | }; 47 | 48 | } 49 | 50 | #endif //LAVOS_RENDERABLE_COMPONENT_H 51 | -------------------------------------------------------------------------------- /lavos/src/texture.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "lavos/texture.h" 3 | #include "lavos/engine.h" 4 | #include "lavos/vk_util.h" 5 | 6 | using namespace lavos; 7 | 8 | Texture Texture::CreateColor(Engine *engine, vk::Format format, glm::vec4 color) 9 | { 10 | auto &device = engine->GetVkDevice(); 11 | 12 | Image image = Image::CreateColor(engine, format, color); 13 | 14 | auto image_view_info = vk::ImageViewCreateInfo() 15 | .setImage(image.image) 16 | .setViewType(vk::ImageViewType::e2D) 17 | .setFormat(image.format) 18 | .setSubresourceRange(vk::ImageSubresourceRange(vk_util::GetFormatIsDepth(format) ? vk::ImageAspectFlagBits::eDepth : vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1)); 19 | 20 | auto image_view = device.createImageView(image_view_info); 21 | 22 | 23 | auto create_info = vk::SamplerCreateInfo() 24 | .setMagFilter(vk::Filter::eNearest) 25 | .setMinFilter(vk::Filter::eNearest) 26 | .setAddressModeU(vk::SamplerAddressMode::eRepeat) 27 | .setAddressModeV(vk::SamplerAddressMode::eRepeat) 28 | .setAddressModeW(vk::SamplerAddressMode::eRepeat) 29 | .setAnisotropyEnable(VK_FALSE) 30 | .setBorderColor(vk::BorderColor::eIntOpaqueBlack) 31 | .setUnnormalizedCoordinates(VK_FALSE) 32 | .setCompareEnable(VK_FALSE) 33 | .setCompareOp(vk::CompareOp::eAlways) 34 | .setMipmapMode(vk::SamplerMipmapMode::eNearest) 35 | .setMipLodBias(0.0f) 36 | .setMinLod(0.0f) 37 | .setMaxLod(0.0f); 38 | 39 | auto sampler = device.createSampler(create_info); 40 | 41 | return Texture(image, image_view, sampler); 42 | } -------------------------------------------------------------------------------- /lavos/glsl/material/gouraud.vf.shader: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | #if SHADER_VERT 4 | 5 | #include "common_vert.glsl" 6 | #include "common_lighting.glsl" 7 | #include "common_camera.glsl" 8 | #include "lighting_phong.glsl" 9 | 10 | layout(set = DESCRIPTOR_SET_INDEX_MATERIAL, binding = 0, std140) uniform MaterialBuffer 11 | { 12 | PhongMaterialParameters phong_params; 13 | } material_uni; 14 | 15 | out gl_PerVertex 16 | { 17 | vec4 gl_Position; 18 | }; 19 | 20 | layout(location = 1) out vec2 uv_out; 21 | layout(location = 2) out vec3 color_out; 22 | 23 | void main() 24 | { 25 | gl_Position = CalculateVertexPosition(); 26 | 27 | vec3 base_color = material_uni.phong_params.base_color.rgb; 28 | vec3 color = base_color.rgb * lighting_uni.ambient_intensity; 29 | 30 | vec3 cam_dir = normalize(camera_uni.position - position_in); 31 | 32 | vec3 normal = normalize(normal_in); 33 | 34 | if(lighting_uni.directional_light_enabled) 35 | { 36 | color += base_color.rgb * LightingPhong(normal, -lighting_uni.directional_light_dir, cam_dir, material_uni.phong_params.specular_exponent); 37 | } 38 | 39 | color_out = color; 40 | uv_out = uv_in; 41 | } 42 | 43 | #elif SHADER_FRAG 44 | 45 | #include "common_frag.glsl" 46 | 47 | layout(set = DESCRIPTOR_SET_INDEX_MATERIAL, binding = 1) uniform sampler2D tex_uni; 48 | 49 | layout(location = 1) in vec2 uv_in; 50 | layout(location = 2) in vec3 color_in; 51 | 52 | void main() 53 | { 54 | vec4 tex_color = texture(tex_uni, uv_in); 55 | out_color = vec4(tex_color.rgb * color_in, tex_color.a); 56 | } 57 | 58 | #endif -------------------------------------------------------------------------------- /lavos/include/lavos/image.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef LAVOS_IMAGE_H 3 | #define LAVOS_IMAGE_H 4 | 5 | #include 6 | #include "vk_mem_alloc.h" 7 | 8 | #include "glm_config.h" 9 | #include 10 | 11 | namespace lavos 12 | { 13 | 14 | class Engine; 15 | 16 | class Image 17 | { 18 | public: 19 | vk::Image image; 20 | VmaAllocation allocation; 21 | vk::Format format; 22 | 23 | Image(std::nullptr_t = nullptr) 24 | : image(nullptr), allocation(nullptr), format(vk::Format::eUndefined) {} 25 | 26 | Image(vk::Image image, VmaAllocation allocation, vk::Format format) 27 | : image(image), allocation(allocation), format(format) {} 28 | 29 | 30 | static Image LoadFromPixelData(Engine *engine, vk::Format format, uint32_t width, uint32_t height, unsigned char *pixels); 31 | static Image LoadFromFile(Engine *engine, std::string file); 32 | static Image LoadFromMemory(Engine *engine, unsigned char *data, size_t size); 33 | static Image CreateColor(Engine *engine, vk::Format format, glm::vec4 color); 34 | 35 | bool operator==(Image const &rhs) const 36 | { 37 | return image == rhs.image 38 | && allocation == rhs.allocation 39 | && format == rhs.format; 40 | } 41 | 42 | bool operator!=(Image const &rhs) const 43 | { 44 | return image != rhs.image 45 | || allocation != rhs.allocation 46 | || format != rhs.format; 47 | } 48 | 49 | explicit operator bool() const { return image; } 50 | bool operator!() const { return !image; } 51 | }; 52 | 53 | 54 | 55 | } 56 | 57 | #endif //VULKAN_IMAGE_H 58 | -------------------------------------------------------------------------------- /lavos/include/lavos/component/point_cloud_component.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef LAVOS_POINT_CLOUD_COMPONENT_H 3 | #define LAVOS_POINT_CLOUD_COMPONENT_H 4 | 5 | #include "component.h" 6 | #include "../renderable.h" 7 | #include "../point_cloud.h" 8 | 9 | namespace lavos 10 | { 11 | 12 | template 13 | class PointCloudComp: public Component, public Renderable, public Renderable::Primitive 14 | { 15 | private: 16 | PointCloud *point_cloud; 17 | MaterialInstance *material_instance; 18 | 19 | public: 20 | PointCloudComp(PointCloud *point_cloud = nullptr) { SetPointCloud(point_cloud); } 21 | 22 | void SetPointCloud(PointCloud *point_cloud) { this->point_cloud = point_cloud; } 23 | PointCloud *GetPointCloud() const { return point_cloud; } 24 | 25 | bool GetCurrentlyRenderable() const 26 | { 27 | return point_cloud != nullptr && material_instance != nullptr; 28 | } 29 | 30 | void BindBuffers(vk::CommandBuffer command_buffer) override 31 | { 32 | command_buffer.bindVertexBuffers(0, { point_cloud->vertex_buffer->GetVkBuffer() }, { 0 }); 33 | } 34 | 35 | unsigned int GetPrimitivesCount() override { return 1; } 36 | Renderable::Primitive *GetPrimitive(unsigned int i) override { return this; } 37 | 38 | MaterialInstance *GetMaterialInstance() override { return material_instance; } 39 | 40 | void Draw(vk::CommandBuffer command_buffer) override 41 | { 42 | command_buffer.draw(static_cast(point_cloud->points.size()), 1, 0, 0); 43 | } 44 | }; 45 | 46 | } 47 | 48 | #endif //LAVOS_POINT_CLOUD_COMPONENT_H 49 | -------------------------------------------------------------------------------- /lavos/include/lavos/material/gouraud_material.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef LAVOS_GOURAUD_MATERIAL_H 3 | #define LAVOS_GOURAUD_MATERIAL_H 4 | 5 | #include "material.h" 6 | 7 | namespace lavos 8 | { 9 | 10 | class GouraudMaterial: public Material 11 | { 12 | private: 13 | struct alignas(sizeof(float)) UniformBuffer 14 | { 15 | glm::vec4 color_factor; 16 | float specular_exponent; 17 | }; 18 | 19 | enum : Material::DescriptorSetId { 20 | DescriptorSetLayoutIdDefault 21 | }; 22 | 23 | void CreateDescriptorSetLayouts(); 24 | 25 | vk::ShaderModule vert_shader_module; 26 | vk::ShaderModule frag_shader_module; 27 | 28 | Texture texture_default_base_color; 29 | Texture texture_default_normal; 30 | 31 | public: 32 | static const Material::ParameterSlot parameter_slot_specular_exponent = 1000; 33 | 34 | GouraudMaterial(Engine *engine); 35 | ~GouraudMaterial(); 36 | 37 | bool GetRenderModeSupport(RenderMode render_mode) const override 38 | { 39 | return render_mode == DefaultRenderMode::ColorForward; 40 | } 41 | 42 | virtual std::vector GetShaderStageCreateInfos(Material::RenderMode render_mode) const override; 43 | 44 | void WriteDescriptorSet(DescriptorSetId id, vk::DescriptorSet descriptor_set, MaterialInstance *instance) override; 45 | 46 | void *CreateInstanceData(InstanceDataId id) override; 47 | void DestroyInstanceData(InstanceDataId id, void *data) override; 48 | void UpdateInstanceData(InstanceDataId id, void *data, MaterialInstance *instance) override; 49 | }; 50 | 51 | } 52 | 53 | 54 | #endif //LAVOS_GOURAUD_MATERIAL_H 55 | -------------------------------------------------------------------------------- /lavos/glsl/material/common_lighting.glsl: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _MATERIAL_COMMON_LIGHTING_GLSL 3 | #define _MATERIAL_COMMON_LIGHTING_GLSL 4 | 5 | #include "common.glsl" 6 | 7 | struct SpotLight 8 | { 9 | vec3 position; 10 | float angle_cos; 11 | vec3 direction; 12 | mat4 shadow_mvp_matrix; 13 | }; 14 | 15 | layout(set = DESCRIPTOR_SET_INDEX_COMMON, binding = DESCRIPTOR_SET_COMMON_BINDING_LIGHTING_BUFFER, std140) uniform LightingBuffer 16 | { 17 | vec3 ambient_intensity; 18 | 19 | bool directional_light_enabled; 20 | vec3 directional_light_dir; 21 | vec3 directional_light_intensity; 22 | 23 | uint spot_lights_count; 24 | 25 | SpotLight spot_lights[MAX_SPOT_LIGHTS_COUNT]; 26 | } lighting_uni; 27 | 28 | layout(set = DESCRIPTOR_SET_INDEX_COMMON, binding = DESCRIPTOR_SET_COMMON_BINDING_SPOT_LIGHT_SHADOW_TEX) uniform sampler2D spot_light_shadow_tex_uni[MAX_SPOT_LIGHTS_COUNT]; 29 | 30 | #if SHADOW_MSM 31 | #include "../lib/msm.glsl" 32 | #endif 33 | 34 | #define SPOT_LIGHT_SHADOW_DEPTH_BIAS 0.0001 35 | 36 | float EvaluateSpotLightShadow(int index, vec3 pos) 37 | { 38 | vec4 shadow_pos = lighting_uni.spot_lights[index].shadow_mvp_matrix * vec4(pos, 1.0); 39 | #if SHADOW_MSM 40 | vec2 uv = shadow_pos.xy * 0.5 / shadow_pos.w + 0.5; 41 | return MSMShadow(texture(spot_light_shadow_tex_uni[index], uv), shadow_pos.z); 42 | #else 43 | shadow_pos /= shadow_pos.w; 44 | vec2 uv = shadow_pos.xy * 0.5 + 0.5; 45 | float shadow_depth = texture(spot_light_shadow_tex_uni[index], uv).r; 46 | float frag_depth = shadow_pos.z - SPOT_LIGHT_SHADOW_DEPTH_BIAS; 47 | return frag_depth < shadow_depth ? 1.0 : 0.0; 48 | #endif 49 | } 50 | 51 | #endif -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5) 2 | project(lavos) 3 | 4 | set(CMAKE_CXX_STANDARD 14) 5 | 6 | option(LAVOS_BUILD_SHELL_GLFW "Build GLFW Lavos Shell library" ON) 7 | option(LAVOS_BUILD_SHELL_QT "Build Qt Lavos Shell library" OFF) 8 | 9 | option(LAVOS_BUILD_DEMOS "Build Demos" ON) 10 | option(LAVOS_BUILD_QT_DEMOS "Build Qt Demo" OFF) 11 | option(LAVOS_BUILD_POINT_CLOUD_DEMO "Build Point Cloud Demo (requires PCL)" OFF) 12 | 13 | list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") 14 | 15 | include_directories("${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/glm") 16 | include_directories("${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/glfw/include") 17 | include_directories("${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/vma/src") 18 | include_directories("${CMAKE_CURRENT_SOURCE_DIR}/thirdparty") 19 | 20 | if(ANDROID) 21 | #include_directories("${CMAKE_CURRENT_SOURCE_DIR}/android/vulkan_wrapper") 22 | include_directories("${CMAKE_SOURCE_DIR}/android/vulkan-hpp" 23 | "${CMAKE_SOURCE_DIR}/android/common") 24 | include_directories("${ANDROID_NDK}/sources/third_party/vulkan/src/include" 25 | "${ANDROID_NDK}/sources/android/native_app_glue") 26 | 27 | set(Vulkan_LIBRARIES vulkan) 28 | 29 | include_directories("${CMAKE_CURRENT_SOURCE_DIR}/android/common") 30 | 31 | add_subdirectory(android) 32 | else() 33 | find_package(Vulkan REQUIRED) 34 | include_directories(${Vulkan_INCLUDE_DIRS}) 35 | endif() 36 | 37 | find_package(VulkanHPP REQUIRED) 38 | include_directories(${VulkanHPP_INCLUDE_DIRS}) 39 | 40 | add_subdirectory(lavos) 41 | add_subdirectory(shell) 42 | 43 | if(LAVOS_BUILD_DEMOS) 44 | add_subdirectory(demos) 45 | endif() 46 | -------------------------------------------------------------------------------- /lavos/include/lavos/point_cloud.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef LAVOS_POINT_CLOUD_H 3 | #define LAVOS_POINT_CLOUD_H 4 | 5 | #include 6 | #include 7 | 8 | #include "engine.h" 9 | #include "vertex.h" 10 | #include "buffer.h" 11 | #include "material/material_instance.h" 12 | 13 | namespace lavos 14 | { 15 | 16 | template 17 | class PointCloud 18 | { 19 | private: 20 | Engine * const engine; 21 | 22 | public: 23 | std::vector points; 24 | 25 | lavos::Buffer *vertex_buffer = nullptr; 26 | 27 | explicit PointCloud(Engine *engine); 28 | ~PointCloud(); 29 | 30 | void CreateVertexBuffer(); 31 | void CreateBuffers(); 32 | }; 33 | 34 | 35 | template 36 | inline PointCloud::PointCloud(Engine *engine) 37 | : engine(engine) 38 | { 39 | } 40 | 41 | template 42 | inline PointCloud::~PointCloud() 43 | { 44 | delete vertex_buffer; 45 | } 46 | 47 | template 48 | inline void PointCloud::CreateVertexBuffer() 49 | { 50 | vk::DeviceSize size = sizeof(points[0]) * points.size(); 51 | 52 | auto staging_buffer = engine->CreateBuffer(size, vk::BufferUsageFlagBits::eTransferSrc, VMA_MEMORY_USAGE_CPU_ONLY); 53 | memcpy(staging_buffer->Map(), points.data(), size); 54 | staging_buffer->UnMap(); 55 | 56 | vertex_buffer = engine->CreateBuffer(size, vk::BufferUsageFlagBits::eTransferDst | vk::BufferUsageFlagBits::eVertexBuffer, 57 | VMA_MEMORY_USAGE_GPU_ONLY); 58 | 59 | engine->CopyBuffer(staging_buffer->GetVkBuffer(), vertex_buffer->GetVkBuffer(), size); 60 | 61 | delete staging_buffer; 62 | } 63 | 64 | template 65 | inline void PointCloud::CreateBuffers() 66 | { 67 | CreateVertexBuffer(); 68 | } 69 | 70 | 71 | } 72 | 73 | 74 | #endif //LAVOS_POINT_CLOUD_H 75 | -------------------------------------------------------------------------------- /lavos/include/lavos/material/phong_material.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef LAVOS_PHONG_MATERIAL_H 3 | #define LAVOS_PHONG_MATERIAL_H 4 | 5 | #include "material.h" 6 | 7 | namespace lavos 8 | { 9 | 10 | class PhongMaterial: public Material 11 | { 12 | private: 13 | struct alignas(sizeof(float)) UniformBuffer 14 | { 15 | glm::vec4 color_factor; 16 | float specular_exponent; 17 | }; 18 | 19 | enum : Material::DescriptorSetId { 20 | DescriptorSetLayoutIdDefault, 21 | DescriptorSetLayoutIdShadow 22 | }; 23 | 24 | vk::ShaderModule vert_shader_module; 25 | vk::ShaderModule frag_shader_module; 26 | 27 | vk::ShaderModule shadow_vert_shader_module; 28 | vk::ShaderModule shadow_frag_shader_module; 29 | 30 | Texture texture_default_base_color; 31 | Texture texture_default_normal; 32 | 33 | void CreateDescriptorSetLayouts(); 34 | 35 | public: 36 | static const Material::ParameterSlot parameter_slot_specular_exponent = 1000; 37 | 38 | PhongMaterial(Engine *engine); 39 | ~PhongMaterial(); 40 | 41 | bool GetRenderModeSupport(RenderMode render_mode) const override 42 | { 43 | return render_mode == DefaultRenderMode::ColorForward 44 | || render_mode == DefaultRenderMode::Shadow; 45 | } 46 | 47 | virtual std::vector GetShaderStageCreateInfos(Material::RenderMode render_mode) const override; 48 | 49 | virtual void WriteDescriptorSet(DescriptorSetId id, vk::DescriptorSet descriptor_set, MaterialInstance *instance) override; 50 | 51 | virtual void *CreateInstanceData(InstanceDataId id) override; 52 | virtual void DestroyInstanceData(InstanceDataId id, void *data) override; 53 | virtual void UpdateInstanceData(InstanceDataId id, void *data, MaterialInstance *instance) override; 54 | }; 55 | 56 | } 57 | 58 | 59 | #endif //VULKAN_PHONG_MATERIAL_H 60 | -------------------------------------------------------------------------------- /android/gltf/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | def layersDir = "${android.ndkDirectory}/sources/third_party/vulkan/src/build-android/jniLibs" 4 | 5 | android { 6 | compileSdkVersion 26 7 | buildToolsVersion "26.0.1" 8 | defaultConfig { 9 | applicationId "com.metallic.vulkan" 10 | minSdkVersion 24 11 | targetSdkVersion 26 12 | versionCode 1 13 | versionName "1.0" 14 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 15 | ndk { 16 | abiFilters 'x86', 'x86_64', 'armeabi-v7a', 'arm64-v8a' 17 | } 18 | externalNativeBuild { 19 | cmake { 20 | arguments "-DMODULE_NAME=${project.name}", 21 | '-DANDROID_PLATFORM=android-24', 22 | '-DANDROID_TOOLCHAIN=clang', 23 | '-DANDROID_STL=gnustl_static' 24 | } 25 | } 26 | } 27 | 28 | buildTypes { 29 | release { 30 | minifyEnabled false 31 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 32 | } 33 | } 34 | 35 | externalNativeBuild { 36 | cmake { 37 | path "../../CMakeLists.txt" 38 | } 39 | } 40 | 41 | sourceSets { 42 | main.jniLibs.srcDirs = ["${layersDir}"] 43 | main.assets.srcDirs = ["src/main/assets", "../../demos/data"] 44 | } 45 | } 46 | dependencies { 47 | implementation fileTree(dir: 'libs', include: ['*.jar']) 48 | implementation 'com.android.support:appcompat-v7:26.1.0' 49 | testImplementation 'junit:junit:4.12' 50 | androidTestImplementation 'com.android.support.test:runner:1.0.1' 51 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1' 52 | } -------------------------------------------------------------------------------- /lavos/src/mesh.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "lavos/mesh.h" 3 | #include "lavos/engine.h" 4 | 5 | #include 6 | 7 | using namespace lavos; 8 | 9 | Mesh::Mesh(Engine *engine) 10 | : engine(engine) 11 | { 12 | } 13 | 14 | Mesh::~Mesh() 15 | { 16 | delete vertex_buffer; 17 | delete index_buffer; 18 | } 19 | 20 | void Mesh::CreateVertexBuffer() 21 | { 22 | vk::DeviceSize size = sizeof(vertices[0]) * vertices.size(); 23 | 24 | auto staging_buffer = engine->CreateBuffer(size, vk::BufferUsageFlagBits::eTransferSrc, VMA_MEMORY_USAGE_CPU_ONLY); 25 | memcpy(staging_buffer->Map(), vertices.data(), size); 26 | staging_buffer->UnMap(); 27 | 28 | vertex_buffer = engine->CreateBuffer(size, vk::BufferUsageFlagBits::eTransferDst | vk::BufferUsageFlagBits::eVertexBuffer, 29 | VMA_MEMORY_USAGE_GPU_ONLY); 30 | 31 | engine->CopyBuffer(staging_buffer->GetVkBuffer(), vertex_buffer->GetVkBuffer(), size); 32 | 33 | delete staging_buffer; 34 | } 35 | 36 | void Mesh::CreateIndexBuffer() 37 | { 38 | vk::DeviceSize size = sizeof(indices[0]) * indices.size(); 39 | 40 | auto staging_buffer = engine->CreateBuffer(size, vk::BufferUsageFlagBits::eTransferSrc, VMA_MEMORY_USAGE_CPU_ONLY); 41 | memcpy(staging_buffer->Map(), indices.data(), size); 42 | staging_buffer->UnMap(); 43 | 44 | index_buffer = engine->CreateBuffer(size, vk::BufferUsageFlagBits::eTransferDst | vk::BufferUsageFlagBits::eIndexBuffer, 45 | VMA_MEMORY_USAGE_GPU_ONLY); 46 | 47 | engine->CopyBuffer(staging_buffer->GetVkBuffer(), index_buffer->GetVkBuffer(), size); 48 | 49 | delete staging_buffer; 50 | } 51 | 52 | void Mesh::CreateBuffers() 53 | { 54 | CreateVertexBuffer(); 55 | CreateIndexBuffer(); 56 | } 57 | 58 | void Mesh::Primitive::Draw(vk::CommandBuffer command_buffer) 59 | { 60 | command_buffer.drawIndexed(indices_count, 1, indices_offset, 0, 0); 61 | } 62 | -------------------------------------------------------------------------------- /lavos/include/lavos/spot_light_shadow.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef LAVOS_SPOT_LIGHT_SHADOW_H 3 | #define LAVOS_SPOT_LIGHT_SHADOW_H 4 | 5 | #include "image.h" 6 | #include "buffer.h" 7 | 8 | #include "glm_config.h" 9 | #include 10 | 11 | namespace lavos 12 | { 13 | 14 | class SpotLight; 15 | class Renderer; 16 | class SpotLightShadowRenderer; 17 | 18 | class SpotLightShadow 19 | { 20 | private: 21 | Engine * const engine; 22 | SpotLight * const light; 23 | SpotLightShadowRenderer * const renderer; 24 | 25 | float near_clip; 26 | float far_clip; 27 | 28 | vk::Filter mag_filter; 29 | vk::Filter min_filter; 30 | 31 | Image depth_image; 32 | vk::ImageView depth_image_view; 33 | 34 | Image shadow_image; 35 | vk::ImageView shadow_image_view; 36 | 37 | Image resolve_image; 38 | vk::ImageView resolve_image_view; 39 | 40 | vk::Sampler sampler; 41 | 42 | vk::Framebuffer framebuffer; 43 | 44 | lavos::Buffer *matrix_uniform_buffer = nullptr; 45 | vk::DescriptorPool descriptor_pool; // TODO: can we make this more global? 46 | vk::DescriptorSet descriptor_set; 47 | 48 | glm::mat4 GetModelViewMatrix(); 49 | glm::mat4 GetProjectionMatrix(); 50 | 51 | void CreateImage(); 52 | void CreateFramebuffer(); 53 | void CreateUniformBuffer(); 54 | void CreateDescriptorPool(); 55 | void CreateDescriptorSet(); 56 | void UpdateMatrixUniformBuffer(); 57 | 58 | public: 59 | SpotLightShadow(Engine *engine, SpotLight *light, SpotLightShadowRenderer *renderer, float near_clip, float far_clip); 60 | ~SpotLightShadow(); 61 | 62 | void Render(vk::CommandBuffer cmd, Renderer *renderer); 63 | 64 | glm::mat4 GetModelViewProjectionMatrix() { return GetProjectionMatrix() * GetModelViewMatrix(); } 65 | Image GetFinalImage(); 66 | vk::ImageView GetFinalImageView(); 67 | vk::Sampler GetSampler() { return sampler; } 68 | }; 69 | 70 | } 71 | 72 | #endif //LAVOS_SPOT_LIGHT_SHADOW_H 73 | -------------------------------------------------------------------------------- /lavos/src/material/point_cloud_material.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "lavos/engine.h" 3 | #include "lavos/material/point_cloud_material.h" 4 | #include "lavos/material/material_instance.h" 5 | 6 | #include "lavos/shader_load.h" 7 | 8 | using namespace lavos; 9 | 10 | PointCloudMaterial::PointCloudMaterial(lavos::Engine *engine) : Material(engine) 11 | { 12 | CreateDescriptorSetLayouts(); 13 | 14 | vert_shader_module = CreateShaderModule(engine->GetVkDevice(), "material/point_cloud.vert"); 15 | frag_shader_module = CreateShaderModule(engine->GetVkDevice(), "material/point_cloud.frag"); 16 | } 17 | 18 | PointCloudMaterial::~PointCloudMaterial() 19 | { 20 | auto &device = engine->GetVkDevice(); 21 | 22 | device.destroyShaderModule(vert_shader_module); 23 | device.destroyShaderModule(frag_shader_module); 24 | } 25 | 26 | void PointCloudMaterial::CreateDescriptorSetLayouts() 27 | { 28 | } 29 | 30 | std::vector PointCloudMaterial::GetShaderStageCreateInfos(RenderMode render_mode) const 31 | { 32 | return { 33 | vk::PipelineShaderStageCreateInfo(vk::PipelineShaderStageCreateFlags(), 34 | vk::ShaderStageFlagBits::eVertex, 35 | vert_shader_module, 36 | "main"), 37 | vk::PipelineShaderStageCreateInfo(vk::PipelineShaderStageCreateFlags(), 38 | vk::ShaderStageFlagBits::eFragment, 39 | frag_shader_module, 40 | "main") 41 | }; 42 | } 43 | 44 | 45 | void PointCloudMaterial::WriteDescriptorSet(DescriptorSetId id, vk::DescriptorSet descriptor_set, MaterialInstance *instance) 46 | { 47 | return; 48 | } 49 | 50 | void *PointCloudMaterial::CreateInstanceData(InstanceDataId id) 51 | { 52 | return nullptr; 53 | } 54 | 55 | void PointCloudMaterial::DestroyInstanceData(InstanceDataId id, void *data_p) 56 | { 57 | } 58 | 59 | void PointCloudMaterial::UpdateInstanceData(InstanceDataId id, void *data_p, MaterialInstance *instance) 60 | { 61 | } -------------------------------------------------------------------------------- /lavos/src/glm_stream.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef VULKAN_GLM_STREAM_H 3 | #define VULKAN_GLM_STREAM_H 4 | 5 | #include "lavos/glm_config.h" 6 | #include 7 | #include 8 | 9 | template 10 | inline std::ostream& operator<<(std::ostream& stream, const glm::tvec2 &v) 11 | { 12 | return stream << "(" << v.x << ", " << v.y << ")"; 13 | } 14 | 15 | template 16 | inline std::ostream& operator<<(std::ostream& stream, const glm::tvec3 &v) 17 | { 18 | return stream << "(" << v.x << ", " << v.y << ", " << v.z << ")"; 19 | } 20 | 21 | template 22 | inline std::ostream& operator<<(std::ostream& stream, const glm::tvec4 &v) 23 | { 24 | return stream << "(" << v.x << ", " << v.y << ", " << v.z << ", " << v.w << ")"; 25 | } 26 | 27 | template 28 | inline std::ostream& operator<<(std::ostream& stream, const glm::tquat &v) 29 | { 30 | return stream << "(" << v.x << ", " << v.y << ", " << v.z << ", " << v.w << ")"; 31 | } 32 | 33 | template 34 | inline std::ostream &operator<<(std::ostream &stream, const glm::tmat3x3 &m) 35 | { 36 | return stream << "(" << m[0].x << ",\t" << m[1].x << ",\t" << m[2].x << ",\n" 37 | << m[0].y << ",\t" << m[1].y << ",\t" << m[2].y << ",\n" 38 | << m[0].z << ",\t" << m[1].z << ",\t" << m[2].z << ")"; 39 | }; 40 | 41 | template 42 | inline std::ostream &operator<<(std::ostream &stream, const glm::tmat4x4 &m) 43 | { 44 | return stream << "(" << m[0].x << ",\t" << m[1].x << ",\t" << m[2].x << ",\t" << m[3].x << ",\n" 45 | << m[0].y << ",\t" << m[1].y << ",\t" << m[2].y << ",\t" << m[3].y << ",\n" 46 | << m[0].z << ",\t" << m[1].z << ",\t" << m[2].z << ",\t" << m[3].z << ",\n" 47 | << m[0].w << ",\t" << m[1].w << ",\t" << m[2].w << ",\t" << m[3].w << ")"; 48 | }; 49 | 50 | #endif //VULKAN_GLM_STREAM_H 51 | -------------------------------------------------------------------------------- /shell/qt/include/lavos_window.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef LAVOS_SHELL_QT_LAVOS_WINDOW_H 3 | #define LAVOS_SHELL_QT_LAVOS_WINDOW_H 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | 14 | namespace lavos { namespace shell { namespace qt 15 | { 16 | 17 | class LavosWindow: public QWindow 18 | { 19 | Q_OBJECT 20 | 21 | public: 22 | class Renderer 23 | { 24 | public: 25 | virtual void InitializeSwapchainResources(LavosWindow *window) =0; 26 | virtual void ReleaseSwapchainResources() =0; 27 | virtual void Render(LavosWindow *window) =0; 28 | }; 29 | 30 | private: 31 | lavos::Engine *engine; 32 | Renderer *renderer; 33 | 34 | bool vulkan_initialized; 35 | 36 | vk::SurfaceKHR surface = nullptr; 37 | uint32_t present_queue_family_index; 38 | vk::Queue present_queue; 39 | lavos::Swapchain *swapchain = nullptr; 40 | lavos::ManagedDepthRenderTarget *depth_render_target = nullptr; 41 | 42 | vk::Semaphore image_available_semaphore = nullptr; 43 | vk::Semaphore render_finished_semaphore = nullptr; 44 | 45 | void RecreateSwapchain(); 46 | void InitializeVulkan(); 47 | void CleanupVulkan(); 48 | 49 | protected: 50 | bool event(QEvent *event) override; 51 | void exposeEvent(QExposeEvent *ev) override; 52 | void resizeEvent(QResizeEvent *ev) override; 53 | 54 | public: 55 | LavosWindow(lavos::Engine *engine, Renderer *renderer, QWindow *parent = nullptr); 56 | virtual ~LavosWindow(); 57 | 58 | void Render(lavos::Renderer *renderer); 59 | 60 | lavos::Engine *GetEngine() const { return engine; } 61 | 62 | lavos::Swapchain *GetSwapchain() const { return swapchain; } 63 | lavos::ManagedDepthRenderTarget *GetDepthRenderTarget() const { return depth_render_target; } 64 | }; 65 | 66 | }}} 67 | 68 | #endif //LAVOS_SHELL_QT_LAVOS_WINDOW_H 69 | -------------------------------------------------------------------------------- /lavos/include/lavos/swapchain.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef LAVOS_SWAPCHAIN_H 3 | #define LAVOS_SWAPCHAIN_H 4 | 5 | #include "render_target.h" 6 | 7 | namespace lavos 8 | { 9 | 10 | class Swapchain : public ColorRenderTarget 11 | { 12 | private: 13 | Engine * const engine; 14 | uint32_t present_queue_family_index; 15 | 16 | vk::SurfaceKHR surface; 17 | 18 | vk::SurfaceFormatKHR surface_format; 19 | vk::PresentModeKHR present_mode; 20 | uint32_t image_count; 21 | vk::Extent2D desired_extent; 22 | 23 | vk::SwapchainKHR swapchain; 24 | vk::Format format; 25 | vk::Extent2D extent; 26 | std::vector images; 27 | std::vector image_views; 28 | 29 | static vk::SurfaceFormatKHR ChooseSurfaceFormat(const std::vector &available_formats); 30 | static vk::PresentModeKHR ChoosePresentMode(const std::vector &available_present_modes); 31 | static vk::Extent2D ChooseExtent(const vk::SurfaceCapabilitiesKHR &capabilities, vk::Extent2D extent); 32 | 33 | void CreateSwapchain(); 34 | void CreateImageViews(); 35 | 36 | void Cleanup(bool destroy_swapchain); 37 | 38 | public: 39 | Swapchain(Engine *engine, vk::SurfaceKHR surface, uint32_t present_queue_family_index, vk::Extent2D desired_extent/*, 40 | std::optional force_surface_format = std::nullopt, 41 | std::optional force_present_mode = std::nullopt, 42 | std::optional force_image_count = std::nullopt*/); 43 | virtual ~Swapchain(); 44 | 45 | void Resize(vk::Extent2D extent); 46 | void Recreate(); 47 | 48 | vk::SwapchainKHR GetSwapchain() { return swapchain; } 49 | 50 | vk::Extent2D GetExtent() const override; // { return extent; } // TODO: should be desired_extent? 51 | vk::Format GetFormat() const override; // { return format; } 52 | std::vector GetImageViews() const override;// { return image_views; } 53 | }; 54 | 55 | } 56 | 57 | #endif //LAVOS_SWAPCHAIN_H 58 | -------------------------------------------------------------------------------- /lavos/include/lavos/material/point_cloud_material.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef LAVOS_POINT_CLOUD_MATERIAL_H 3 | #define LAVOS_POINT_CLOUD_MATERIAL_H 4 | 5 | #include "material.h" 6 | 7 | #include "../glm_config.h" 8 | #include 9 | 10 | namespace lavos 11 | { 12 | 13 | class PointCloudMaterial : public Material 14 | { 15 | private: 16 | void CreateDescriptorSetLayouts(); 17 | 18 | vk::ShaderModule vert_shader_module; 19 | vk::ShaderModule frag_shader_module; 20 | 21 | public: 22 | PointCloudMaterial(Engine *engine); 23 | ~PointCloudMaterial(); 24 | 25 | bool GetRenderModeSupport(RenderMode render_mode) const override 26 | { 27 | return render_mode == DefaultRenderMode::ColorForward; 28 | } 29 | 30 | std::vector GetShaderStageCreateInfos(RenderMode render_mode) const override; 31 | 32 | void WriteDescriptorSet(DescriptorSetId id, vk::DescriptorSet descriptor_set, MaterialInstance *instance) override; 33 | void *CreateInstanceData(InstanceDataId id) override; 34 | void DestroyInstanceData(InstanceDataId id, void *data) override; 35 | void UpdateInstanceData(InstanceDataId id, void *data, MaterialInstance *instance) override; 36 | 37 | vk::PrimitiveTopology GetPrimitiveTopology() override { return vk::PrimitiveTopology::ePointList; } 38 | 39 | std::vector GetVertexInputBindingDescriptions() override 40 | { 41 | return { 42 | vk::VertexInputBindingDescription() 43 | .setBinding(0) 44 | .setStride(sizeof(glm::vec3)) 45 | .setInputRate(vk::VertexInputRate::eVertex) 46 | }; 47 | } 48 | 49 | std::vector GetVertexInputAttributeDescriptions() override 50 | { 51 | return { 52 | vk::VertexInputAttributeDescription() 53 | .setBinding(0) 54 | .setLocation(0) 55 | .setFormat(vk::Format::eR32G32B32Sfloat) 56 | .setOffset(0), 57 | }; 58 | } 59 | }; 60 | 61 | } 62 | 63 | #endif //LAVOS_POINT_CLOUD_MATERIAL_H 64 | -------------------------------------------------------------------------------- /lavos/include/lavos/spot_light_shadow_renderer.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef LAVOS_SPOT_LIGHT_SHADOW_RENDERER_H 3 | #define LAVOS_SPOT_LIGHT_SHADOW_RENDERER_H 4 | 5 | #include "sub_renderer.h" 6 | #include "material_pipeline_manager.h" 7 | 8 | #include 9 | #include 10 | 11 | namespace lavos 12 | { 13 | 14 | class Engine; 15 | 16 | class SpotLightShadowRenderer : public SubRenderer 17 | { 18 | private: 19 | std::uint32_t width; 20 | std::uint32_t height; 21 | vk::SampleCountFlagBits samples; 22 | vk::Format depth_format; 23 | vk::Format shadow_format; 24 | 25 | vk::DescriptorSetLayout descriptor_set_layout; // TODO: scope of this could be higher (common for all SpotLightShadowRenderers) 26 | vk::RenderPass render_pass; // TODO: scope of this could be higher (depends only on format) 27 | 28 | MaterialPipelineManager *material_pipeline_manager; 29 | 30 | MaterialPipelineConfiguration CreateMaterialPipelineConfiguration(); 31 | 32 | void CreateRenderPass(); 33 | void CreateDescriptorSetLayout(); 34 | 35 | public: 36 | SpotLightShadowRenderer(lavos::Engine *engine, std::uint32_t width, std::uint32_t height, vk::SampleCountFlagBits samples); 37 | ~SpotLightShadowRenderer() override; 38 | 39 | std::uint32_t GetWidth() const { return width; } 40 | std::uint32_t GetHeight() const { return height; } 41 | vk::SampleCountFlagBits GetSamples() const { return samples; } 42 | vk::Format GetDepthFormat() const { return depth_format; } 43 | vk::Format GetShadowFormat() const { return shadow_format; } 44 | vk::RenderPass GetRenderPass() const { return render_pass; } 45 | vk::DescriptorSetLayout GetDescriptorSetLayout() const { return descriptor_set_layout; } 46 | 47 | MaterialPipelineManager *GetMaterialPipelineManager() const { return material_pipeline_manager; } 48 | 49 | void AddMaterial(Material *material) override; 50 | void RemoveMaterial(Material *material) override; 51 | }; 52 | 53 | } 54 | 55 | #endif //LAVOS_SPOT_LIGHT_SHADOW_RENDERER_H 56 | -------------------------------------------------------------------------------- /shell/glfw/include/window_application.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef LAVOS_SHELL_GLFW_WINDOW_APPLICATION_H 3 | #define LAVOS_SHELL_GLFW_WINDOW_APPLICATION_H 4 | 5 | #include 6 | 7 | #define GLFW_INCLUDE_VULKAN 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | namespace lavos { namespace shell { namespace glfw 15 | { 16 | 17 | 18 | class WindowApplication 19 | { 20 | private: 21 | GLFWwindow *window; 22 | static void OnWindowResized(GLFWwindow *window, int width, int height); 23 | 24 | lavos::Engine *engine; 25 | 26 | vk::SurfaceKHR surface; 27 | 28 | uint32_t present_queue_family_index; 29 | vk::Queue present_queue; 30 | 31 | lavos::Swapchain *swapchain; 32 | lavos::ManagedDepthRenderTarget *depth_render_target; 33 | 34 | vk::Semaphore image_available_semaphore; 35 | vk::Semaphore render_finished_semaphore; 36 | 37 | std::chrono::high_resolution_clock::time_point last_frame_time; 38 | float delta_time = 0.0f; 39 | 40 | virtual void InitWindow(int width, int height, std::string title); 41 | virtual void InitVulkan(bool enable_layers); 42 | 43 | virtual void OnWindowResized(int width, int height); 44 | 45 | 46 | void CreateEngine(bool enable_layers); 47 | 48 | void CreateSurface(); 49 | 50 | void RecreateSwapchain(); 51 | 52 | void Cleanup(); 53 | 54 | void CreateSemaphores(); 55 | 56 | public: 57 | WindowApplication(int width, int height, std::string title, bool enable_layers); 58 | ~WindowApplication(); 59 | 60 | void BeginFrame(); 61 | void Update(); 62 | void Render(lavos::Renderer *renderer); 63 | void EndFrame(); 64 | 65 | GLFWwindow *GetWindow() const { return window; } 66 | float GetDeltaTime() const { return delta_time; } 67 | 68 | lavos::Engine *GetEngine() const { return engine; } 69 | lavos::Swapchain *GetSwapchain() const { return swapchain; } 70 | lavos::DepthRenderTarget *GetDepthRenderTarget() const { return depth_render_target; } 71 | }; 72 | 73 | }}} 74 | 75 | #endif //LAVOS_SHELL_GLFW_WINDOW_APPLICATION_H 76 | -------------------------------------------------------------------------------- /lavos/include/lavos/vertex.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef LAVOS_VERTEX_H 3 | #define LAVOS_VERTEX_H 4 | 5 | #include "glm_config.h" 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | #include 14 | 15 | namespace lavos 16 | { 17 | 18 | struct alignas(sizeof(float)) Vertex 19 | { 20 | glm::vec3 pos; 21 | glm::vec2 uv; 22 | glm::vec3 normal; 23 | glm::vec3 tang; 24 | glm::vec3 bitang; 25 | 26 | void SetNormalTangComputeBitang(const glm::vec3 &normal, const glm::vec4 &tang) 27 | { 28 | this->normal = normal; 29 | this->tang = glm::vec3(tang.x, tang.y, tang.z); 30 | this->bitang = glm::cross(normal, this->tang) * tang.w; 31 | } 32 | 33 | static vk::VertexInputBindingDescription GetBindingDescription() 34 | { 35 | return vk::VertexInputBindingDescription() 36 | .setBinding(0) 37 | .setStride(sizeof(Vertex)) 38 | .setInputRate(vk::VertexInputRate::eVertex); 39 | } 40 | 41 | static std::vector GetAttributeDescription() 42 | { 43 | return { 44 | vk::VertexInputAttributeDescription() 45 | .setBinding(0) 46 | .setLocation(0) 47 | .setFormat(vk::Format::eR32G32B32Sfloat) 48 | .setOffset(static_cast(offsetof(Vertex, pos))), 49 | 50 | vk::VertexInputAttributeDescription() 51 | .setBinding(0) 52 | .setLocation(1) 53 | .setFormat(vk::Format::eR32G32Sfloat) 54 | .setOffset(static_cast(offsetof(Vertex, uv))), 55 | 56 | vk::VertexInputAttributeDescription() 57 | .setBinding(0) 58 | .setLocation(2) 59 | .setFormat(vk::Format::eR32G32B32Sfloat) 60 | .setOffset(static_cast(offsetof(Vertex, normal))), 61 | 62 | vk::VertexInputAttributeDescription() 63 | .setBinding(0) 64 | .setLocation(3) 65 | .setFormat(vk::Format::eR32G32B32Sfloat) 66 | .setOffset(static_cast(offsetof(Vertex, tang))), 67 | 68 | vk::VertexInputAttributeDescription() 69 | .setBinding(0) 70 | .setLocation(4) 71 | .setFormat(vk::Format::eR32G32B32Sfloat) 72 | .setOffset(static_cast(offsetof(Vertex, bitang))), 73 | }; 74 | }; 75 | }; 76 | 77 | } 78 | 79 | #endif //VULKAN_VERTEX_H 80 | -------------------------------------------------------------------------------- /lavos/src/node.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | #include "lavos/node.h" 7 | #include "lavos/component/transform_component.h" 8 | 9 | 10 | using namespace lavos; 11 | 12 | Node::Node() 13 | { 14 | } 15 | 16 | Node::~Node() 17 | { 18 | for(auto component : components) 19 | delete component; 20 | 21 | for(auto child : children) 22 | delete child; 23 | } 24 | 25 | void Node::AddComponent(lavos::Component *component) 26 | { 27 | if(component->GetNode() != nullptr) 28 | throw std::runtime_error("component is already added to a node."); 29 | 30 | for(const auto &c: components) 31 | { 32 | if(c == component) 33 | return; 34 | } 35 | 36 | components.push_back(component); 37 | 38 | component->node = this; 39 | 40 | auto transform_component = dynamic_cast(component); 41 | if(transform_component != nullptr) 42 | this->transform_component = transform_component; 43 | } 44 | 45 | void Node::RemoveComponent(Component *component) 46 | { 47 | if(transform_component == component) 48 | transform_component = nullptr; 49 | 50 | for(auto it=components.begin(); it!=components.end(); it++) 51 | { 52 | if(*it == component) 53 | { 54 | components.erase(it); 55 | component->node = nullptr; 56 | return; 57 | } 58 | } 59 | } 60 | 61 | void Node::AddChild(Node *node) 62 | { 63 | if(node->parent != nullptr && !node->is_root) 64 | throw std::runtime_error("node is already child of another node or is root node."); 65 | 66 | node->parent = this; 67 | children.push_back(node); 68 | } 69 | 70 | void Node::RemoveChild(Node *node) 71 | { 72 | if(node->parent != this) 73 | throw std::runtime_error("node is not child of this node"); 74 | 75 | for(auto it=children.begin(); it!=children.end(); it++) 76 | { 77 | if(*it == node) 78 | { 79 | children.erase(it); 80 | node->parent = nullptr; 81 | return; 82 | } 83 | } 84 | } 85 | 86 | void Node::TraversePreOrder(std::function func) 87 | { 88 | func(this); 89 | 90 | for(auto &child : children) 91 | child->TraversePreOrder(func); 92 | } 93 | 94 | void Node::TraversePostOrder(std::function func) 95 | { 96 | for(auto &child : children) 97 | child->TraversePreOrder(func); 98 | 99 | func(this); 100 | } 101 | -------------------------------------------------------------------------------- /demos/qt_shell/lavos_renderer.cpp: -------------------------------------------------------------------------------- 1 | 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "lavos_window.h" 10 | #include "lavos_renderer.h" 11 | 12 | 13 | LavosWindowRenderer::LavosWindowRenderer(lavos::Engine *engine) 14 | : engine(engine) 15 | { 16 | } 17 | 18 | LavosWindowRenderer::~LavosWindowRenderer() 19 | { 20 | } 21 | 22 | void LavosWindowRenderer::InitializeSwapchainResources(lavos::shell::qt::LavosWindow *window) 23 | { 24 | material = new lavos::PhongMaterial(engine); 25 | 26 | render_config = lavos::RenderConfigBuilder().Build(); 27 | 28 | asset_container = lavos::AssetContainer::LoadFromGLTF(engine, render_config, material, "data/gltftest.gltf"); 29 | 30 | scene = asset_container->scenes[0]; 31 | scene->SetAmbientLightIntensity(glm::vec3(0.3f, 0.3f, 0.3f)); 32 | 33 | camera = scene->GetRootNode()->GetComponentInChildren(); 34 | 35 | if(camera == nullptr) 36 | { 37 | lavos::Node *camera_node = new lavos::Node(); 38 | scene->GetRootNode()->AddChild(camera_node); 39 | 40 | camera_node->AddComponent(new lavos::TransformComp()); 41 | 42 | camera_node->GetTransformComp()->translation = glm::vec3(5.0f, 5.0f, 5.0f); 43 | camera_node->GetTransformComp()->SetLookAt(glm::vec3(0.0f, 0.0f, 0.0f)); 44 | 45 | camera = new lavos::Camera(); 46 | camera->SetNearClip(0.01f); 47 | camera_node->AddComponent(camera); 48 | } 49 | 50 | lavos::Node *light_node = new lavos::Node(); 51 | scene->GetRootNode()->AddChild(light_node); 52 | 53 | light_node->AddComponent(new lavos::TransformComp()); 54 | light_node->GetTransformComp()->SetLookAt(glm::vec3(-1.0f, -1.0f, -1.0f)); 55 | 56 | lavos::DirectionalLight *light = new lavos::DirectionalLight(); 57 | light_node->AddComponent(light); 58 | 59 | renderer = new lavos::Renderer(engine, render_config, window->GetSwapchain(), window->GetDepthRenderTarget()); 60 | renderer->AddMaterial(material); 61 | 62 | renderer->SetScene(scene); 63 | renderer->SetCamera(camera); 64 | } 65 | 66 | void LavosWindowRenderer::ReleaseSwapchainResources() 67 | { 68 | delete renderer; 69 | delete asset_container; 70 | delete material; 71 | } 72 | 73 | void LavosWindowRenderer::Render(lavos::shell::qt::LavosWindow *window) 74 | { 75 | window->Render(renderer); 76 | } 77 | 78 | -------------------------------------------------------------------------------- /lavos/src/render_target.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "lavos/render_target.h" 3 | 4 | using namespace lavos; 5 | 6 | void RenderTarget::AddChangedCallback(ChangedCallbackOrder order, ChangedCallback *callback) 7 | { 8 | RemoveChangedCallback(callback); 9 | changed_callbacks.insert(std::pair(order, callback)); 10 | } 11 | 12 | void RenderTarget::RemoveChangedCallback(ColorRenderTarget::ChangedCallback *callback) 13 | { 14 | for(auto i=changed_callbacks.begin(); i!=changed_callbacks.end(); i++) 15 | { 16 | if(i->second == callback) 17 | { 18 | changed_callbacks.erase(i); 19 | return; 20 | } 21 | } 22 | } 23 | 24 | void RenderTarget::SignalChangedCallbacks() 25 | { 26 | for(auto callback : changed_callbacks) 27 | { 28 | callback.second->RenderTargetChanged(this); 29 | } 30 | } 31 | 32 | 33 | // ------------------------------------------ 34 | 35 | 36 | ManagedDepthRenderTarget::ManagedDepthRenderTarget(Engine *engine, ColorRenderTarget *color_render_target) 37 | : engine(engine), 38 | color_render_target(color_render_target) 39 | { 40 | CreateResources(); 41 | color_render_target->AddChangedCallback(RenderTarget::ChangedCallbackOrder::AssociatedRenderTarget, this); 42 | } 43 | 44 | ManagedDepthRenderTarget::~ManagedDepthRenderTarget() 45 | { 46 | CleanupResources(); 47 | } 48 | 49 | void ManagedDepthRenderTarget::CreateResources() 50 | { 51 | auto extent = color_render_target->GetExtent(); 52 | 53 | format = engine->FindDepthFormat(); 54 | 55 | image = engine->Create2DImage(extent.width, extent.height, format, 56 | vk::ImageTiling::eOptimal, vk::ImageUsageFlagBits::eDepthStencilAttachment, 57 | VMA_MEMORY_USAGE_GPU_ONLY); 58 | 59 | image_view = engine->GetVkDevice().createImageView(vk::ImageViewCreateInfo() 60 | .setImage(image.image) 61 | .setViewType(vk::ImageViewType::e2D) 62 | .setFormat(format) 63 | .setSubresourceRange(vk::ImageSubresourceRange(vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1))); 64 | 65 | engine->TransitionImageLayout(image.image, format, vk::ImageLayout::eUndefined, vk::ImageLayout::eDepthStencilAttachmentOptimal); 66 | } 67 | 68 | void ManagedDepthRenderTarget::CleanupResources() 69 | { 70 | engine->GetVkDevice().destroyImageView(image_view); 71 | engine->DestroyImage(image); 72 | } 73 | 74 | void ManagedDepthRenderTarget::RenderTargetChanged(RenderTarget *render_target) 75 | { 76 | CleanupResources(); 77 | CreateResources(); 78 | } -------------------------------------------------------------------------------- /lavos/src/material/material.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "lavos/material/material.h" 3 | #include "lavos/engine.h" 4 | #include "lavos/vertex.h" 5 | 6 | #include "lavos/shader_load.h" 7 | 8 | using namespace lavos; 9 | 10 | Material::Material(lavos::Engine *engine) 11 | : engine(engine) 12 | { 13 | } 14 | 15 | Material::~Material() 16 | { 17 | for(auto &it : descriptor_set_layouts) 18 | engine->GetVkDevice().destroyDescriptorSetLayout(it.second.layout); 19 | } 20 | 21 | void Material::CreateDescriptorSetLayout(DescriptorSetId id, 22 | const std::vector &bindings) 23 | { 24 | assert(descriptor_set_layouts.find(id) == descriptor_set_layouts.end()); 25 | 26 | auto create_info = vk::DescriptorSetLayoutCreateInfo() 27 | .setBindingCount(static_cast(bindings.size())) 28 | .setPBindings(bindings.data()); 29 | 30 | DescriptorSetLayout layout; 31 | layout.layout = engine->GetVkDevice().createDescriptorSetLayout(create_info); 32 | 33 | std::map descriptor_counts; 34 | for(auto binding : bindings) 35 | { 36 | if(descriptor_counts.find(binding.descriptorType) == descriptor_counts.end()) 37 | descriptor_counts[binding.descriptorType] = 1; 38 | else 39 | descriptor_counts[binding.descriptorType]++; 40 | } 41 | 42 | layout.pool_sizes.resize(descriptor_counts.size()); 43 | int i=0; 44 | for(auto it : descriptor_counts) 45 | layout.pool_sizes[i++] = vk::DescriptorPoolSize(it.first, it.second); 46 | 47 | descriptor_set_layouts[id] = layout; 48 | } 49 | 50 | const Material::DescriptorSetLayout *Material::GetDescriptorSetLayout(DescriptorSetId id) const 51 | { 52 | auto it = descriptor_set_layouts.find(id); 53 | if(it == descriptor_set_layouts.end()) 54 | return nullptr; 55 | return &it->second; 56 | } 57 | 58 | vk::ShaderModule Material::CreateShaderModule(vk::Device device, std::string shader) 59 | { 60 | size_t size; 61 | const uint32_t *code = GetSPIRVShader(shader, &size); 62 | 63 | return device.createShaderModule( 64 | vk::ShaderModuleCreateInfo() 65 | .setCodeSize(size) 66 | .setPCode(code)); 67 | } 68 | 69 | std::vector Material::GetVertexInputBindingDescriptions() 70 | { 71 | return { Vertex::GetBindingDescription() }; 72 | } 73 | 74 | std::vector Material::GetVertexInputAttributeDescriptions() 75 | { 76 | return Vertex::GetAttributeDescription(); 77 | } 78 | 79 | Material::UBOInstanceData::UBOInstanceData(lavos::Buffer *uniform_buffer) 80 | : uniform_buffer(uniform_buffer) 81 | { 82 | } 83 | 84 | Material::UBOInstanceData::~UBOInstanceData() 85 | { 86 | delete uniform_buffer; 87 | } 88 | -------------------------------------------------------------------------------- /lavos/include/lavos/material_pipeline_manager.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef LAVOS_MATERIAL_PIPELINE_MANAGER_H 3 | #define LAVOS_MATERIAL_PIPELINE_MANAGER_H 4 | 5 | #include 6 | #include 7 | 8 | #include "material/material.h" 9 | #include "vk_util.h" 10 | 11 | namespace lavos 12 | { 13 | 14 | class Engine; 15 | class Renderer; 16 | 17 | struct MaterialPipeline 18 | { 19 | Material *material; 20 | 21 | vk::PipelineLayout pipeline_layout; 22 | vk::Pipeline pipeline; 23 | 24 | int renderer_descriptor_set_index; 25 | int material_descriptor_set_index; 26 | 27 | MaterialPipeline(Material *material) : 28 | material(material) {} 29 | }; 30 | 31 | struct MaterialPipelineConfiguration 32 | { 33 | vk::Extent2D extent; 34 | vk::SampleCountFlagBits samples; 35 | vk::DescriptorSetLayout renderer_descriptor_set_layout; 36 | vk::RenderPass render_pass; 37 | Material::RenderMode render_mode; 38 | vk_util::PipelineColorBlendStateCreateInfo color_blend_state_info; 39 | 40 | MaterialPipelineConfiguration(vk::Extent2D extent, 41 | vk::SampleCountFlagBits samples, 42 | vk::DescriptorSetLayout renderer_descriptor_set_layout, 43 | vk::RenderPass render_pass, 44 | Material::RenderMode render_mode, 45 | const vk_util::PipelineColorBlendStateCreateInfo &color_blend_state_info) 46 | : extent(extent), 47 | samples(samples), 48 | renderer_descriptor_set_layout(renderer_descriptor_set_layout), 49 | render_pass(render_pass), 50 | render_mode(render_mode), 51 | color_blend_state_info(color_blend_state_info) {} 52 | }; 53 | 54 | static inline bool operator==(const MaterialPipelineConfiguration &a, const MaterialPipelineConfiguration &b) 55 | { 56 | return a.extent == b.extent 57 | && a.renderer_descriptor_set_layout == b.renderer_descriptor_set_layout 58 | && a.render_pass == b.render_pass; 59 | } 60 | 61 | class MaterialPipelineManager 62 | { 63 | private: 64 | Engine * const engine; 65 | 66 | MaterialPipelineConfiguration config; 67 | 68 | std::vector material_pipelines; 69 | 70 | MaterialPipeline CreateMaterialPipeline(Material *material, Material::RenderMode render_mode); 71 | void DestroyMaterialPipeline(const MaterialPipeline &material_pipeline); 72 | 73 | void DestroyAllMaterialPipelines(); 74 | void RecreateAllMaterialPipelines(); 75 | 76 | public: 77 | MaterialPipelineManager(Engine *engine, const MaterialPipelineConfiguration &config); 78 | ~MaterialPipelineManager(); 79 | 80 | void AddMaterial(Material *material); 81 | void RemoveMaterial(Material *material); 82 | 83 | void SetConfiguration(const MaterialPipelineConfiguration &config); 84 | 85 | MaterialPipeline *GetMaterialPipeline(Material *material); 86 | }; 87 | 88 | } 89 | 90 | #endif //LAVOS_MATERIAL_PIPELINE_MANAGER_H 91 | -------------------------------------------------------------------------------- /android/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /demos/qt_qvulkanwindow/mainwindow.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "mainwindow.h" 9 | 10 | void MainWindowRenderer::initResources() 11 | { 12 | engine->InitializeWithDevice(window->physicalDevice(), 13 | window->device(), 14 | window->graphicsQueue()); 15 | 16 | material = new lavos::PhongMaterial(engine); 17 | 18 | render_config = lavos::RenderConfigBuilder().Build(); 19 | 20 | asset_container = lavos::AssetContainer::LoadFromGLTF(engine, render_config, material, "data/gltftest.gltf"); 21 | 22 | scene = asset_container->scenes[0]; 23 | scene->SetAmbientLightIntensity(glm::vec3(0.3f, 0.3f, 0.3f)); 24 | 25 | camera = scene->GetRootNode()->GetComponentInChildren(); 26 | 27 | if(camera == nullptr) 28 | { 29 | lavos::Node *camera_node = new lavos::Node(); 30 | scene->GetRootNode()->AddChild(camera_node); 31 | 32 | camera_node->AddComponent(new lavos::TransformComp()); 33 | 34 | camera_node->GetTransformComp()->translation = glm::vec3(5.0f, 5.0f, 5.0f); 35 | camera_node->GetTransformComp()->SetLookAt(glm::vec3(0.0f, 0.0f, 0.0f)); 36 | 37 | camera = new lavos::Camera(); 38 | camera->SetNearClip(0.01f); 39 | camera_node->AddComponent(camera); 40 | } 41 | 42 | lavos::Node *light_node = new lavos::Node(); 43 | scene->GetRootNode()->AddChild(light_node); 44 | 45 | light_node->AddComponent(new lavos::TransformComp()); 46 | light_node->GetTransformComp()->SetLookAt(glm::vec3(-1.0f, -1.0f, -1.0f)); 47 | 48 | lavos::DirectionalLight *light = new lavos::DirectionalLight(); 49 | light_node->AddComponent(light); 50 | } 51 | 52 | void MainWindowRenderer::initSwapChainResources() 53 | { 54 | if(color_render_target != nullptr) 55 | { 56 | color_render_target->SwapchainChanged(); 57 | return; 58 | } 59 | 60 | color_render_target = new QVulkanWindowColorRenderTarget(window); 61 | depth_render_target = new QVulkanWindowDepthRenderTarget(window); 62 | 63 | renderer = new lavos::Renderer(engine, render_config, color_render_target, depth_render_target); 64 | renderer->AddMaterial(material); 65 | 66 | renderer->SetScene(scene); 67 | renderer->SetCamera(camera); 68 | } 69 | 70 | void MainWindowRenderer::releaseSwapChainResources() 71 | { 72 | } 73 | 74 | void MainWindowRenderer::releaseResources() 75 | { 76 | delete renderer; 77 | delete depth_render_target; 78 | delete color_render_target; 79 | delete asset_container; 80 | delete material; 81 | delete engine; 82 | } 83 | 84 | void MainWindowRenderer::startNextFrame() 85 | { 86 | renderer->DrawFrame(static_cast(window->currentSwapChainImageIndex()), {}, {}, {}); 87 | window->frameReady(); 88 | } 89 | -------------------------------------------------------------------------------- /lavos/include/lavos/material/material_instance.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef LAVOS_MATERIAL_INSTANCE_H 3 | #define LAVOS_MATERIAL_INSTANCE_H 4 | 5 | #include 6 | #include 7 | 8 | #include "../texture.h" 9 | #include "../buffer.h" 10 | #include "material.h" 11 | #include "../render_config.h" 12 | 13 | #include "../glm_config.h" 14 | #include 15 | #include 16 | 17 | namespace lavos 18 | { 19 | 20 | class Engine; 21 | class Material; 22 | 23 | class MaterialInstance 24 | { 25 | public: 26 | struct Parameter 27 | { 28 | union 29 | { 30 | float f; 31 | glm::vec2 v2; 32 | glm::vec3 v3; 33 | glm::vec4 v4 = glm::vec4(0.0f); 34 | }; 35 | 36 | Parameter(float value) { f = value; } 37 | Parameter(const glm::vec2 &value) { v2 = value; } 38 | Parameter(const glm::vec3 &value) { v3 = value; } 39 | Parameter(const glm::vec4 &value) { v4 = value; } 40 | }; 41 | 42 | private: 43 | Material * const material; 44 | 45 | std::map textures; 46 | std::map parameters; 47 | 48 | vk::DescriptorPool descriptor_pool; 49 | 50 | std::map descriptor_sets; 51 | std::map instance_data; 52 | 53 | void CreateDescriptorSet(Material::DescriptorSetId id); 54 | void CreateInstanceData(Material::InstanceDataId id); 55 | 56 | void WriteDescriptorSet(Material::DescriptorSetId id); 57 | void WriteInstanceData(Material::InstanceDataId id); 58 | 59 | public: 60 | MaterialInstance(Material *material, const RenderConfig &config, vk::DescriptorPool descriptor_pool); 61 | ~MaterialInstance(); 62 | 63 | Material *GetMaterial() const { return material; } 64 | 65 | void WriteAllData(); 66 | 67 | vk::DescriptorSet GetDescriptorSet(Material::RenderMode render_mode) const { auto it = descriptor_sets.find(render_mode); return it == descriptor_sets.end() ? vk::DescriptorSet() : it->second; } 68 | void *GetInstanceData(Material::RenderMode render_mode) const { auto it = instance_data.find(render_mode); return it == instance_data.end() ? nullptr : it->second; } 69 | 70 | void SetTexture(Material::TextureSlot slot, Texture texture); 71 | Texture *GetTexture(Material::TextureSlot slot); 72 | 73 | void SetParameter(Material::ParameterSlot slot, Parameter parameter); 74 | Parameter *GetParameter(Material::ParameterSlot slot); 75 | float GetParameter(Material::ParameterSlot slot, float default_value); 76 | glm::vec2 GetParameter(Material::ParameterSlot slot, glm::vec2 default_value); 77 | glm::vec3 GetParameter(Material::ParameterSlot slot, glm::vec3 default_value); 78 | glm::vec4 GetParameter(Material::ParameterSlot slot, glm::vec4 default_value); 79 | }; 80 | 81 | } 82 | 83 | #endif //VULKAN_MATERIAL_H 84 | -------------------------------------------------------------------------------- /lavos/glsl/material/phong.vf.shader: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | #if SHADER_VERT 4 | 5 | #include "common_vert.glsl" 6 | 7 | out gl_PerVertex 8 | { 9 | vec4 gl_Position; 10 | }; 11 | 12 | layout(location = 0) out vec2 uv_out; 13 | 14 | layout(location = 1) out vec3 position_out; 15 | layout(location = 2) out vec3 normal_out; 16 | layout(location = 3) out vec3 tang_out; 17 | layout(location = 4) out vec3 bitang_out; 18 | 19 | void main() 20 | { 21 | uv_out = uv_in; 22 | 23 | position_out = (transform_push_constant.transform * vec4(position_in, 1.0)).xyz; 24 | normal_out = mat3(transform_push_constant.transform) * normal_in; 25 | tang_out = mat3(transform_push_constant.transform) * tang_in; 26 | bitang_out = mat3(transform_push_constant.transform) * bitang_in; 27 | 28 | gl_Position = CalculateVertexPosition(); 29 | } 30 | 31 | #elif SHADER_FRAG 32 | 33 | #include "common_frag.glsl" 34 | #include "common_lighting.glsl" 35 | #include "common_camera.glsl" 36 | #include "lighting_phong.glsl" 37 | 38 | layout(set = DESCRIPTOR_SET_INDEX_MATERIAL, binding = 0, std140) uniform MaterialBuffer 39 | { 40 | PhongMaterialParameters phong_params; 41 | } material_uni; 42 | 43 | layout(set = DESCRIPTOR_SET_INDEX_MATERIAL, binding = 1) uniform sampler2D base_color_tex_uni; 44 | layout(set = DESCRIPTOR_SET_INDEX_MATERIAL, binding = 2) uniform sampler2D normal_tex_uni; 45 | 46 | 47 | layout(location = 0) in vec2 uv_in; 48 | 49 | layout(location = 1) in vec3 position_in; 50 | layout(location = 2) in vec3 normal_in; 51 | layout(location = 3) in vec3 tang_in; 52 | layout(location = 4) in vec3 bitang_in; 53 | 54 | 55 | 56 | void main() 57 | { 58 | vec4 base_color = texture(base_color_tex_uni, uv_in).rgba; 59 | base_color *= material_uni.phong_params.base_color; 60 | 61 | vec3 normal = normalize(normal_in); 62 | vec3 tang = normalize(tang_in); 63 | vec3 bitang = normalize(bitang_in); 64 | 65 | vec3 tang_normal = texture(normal_tex_uni, uv_in).rgb * 2.0 - 1.0; 66 | normal = mat3(tang, bitang, normal) * tang_normal; 67 | normal = normalize(normal); 68 | 69 | vec3 cam_dir = normalize(camera_uni.position - position_in); 70 | 71 | vec3 color = base_color.rgb * lighting_uni.ambient_intensity; 72 | 73 | if(lighting_uni.directional_light_enabled) 74 | { 75 | color += base_color.rgb * LightingPhong(normal, -lighting_uni.directional_light_dir, cam_dir, material_uni.phong_params.specular_exponent); 76 | } 77 | 78 | for(int i=0; i 6 | 7 | #include "engine.h" 8 | 9 | namespace lavos 10 | { 11 | 12 | /** 13 | * A RenderTarget is something that can be rendered into. 14 | */ 15 | class RenderTarget 16 | { 17 | public: 18 | class ChangedCallback 19 | { 20 | friend class RenderTarget; 21 | 22 | public: 23 | virtual ~ChangedCallback() = default; 24 | 25 | protected: 26 | /** 27 | * Called e.g. when the {@link RenderTarget}'s extent changes. 28 | * @param render_target 29 | */ 30 | virtual void RenderTargetChanged(RenderTarget *render_target) =0; 31 | }; 32 | 33 | /** 34 | * Defines in which order {@link RenderTarget::ChangedCallback}s are invoked. 35 | */ 36 | enum class ChangedCallbackOrder { 37 | AssociatedRenderTarget = 0, 38 | Renderer 39 | }; 40 | 41 | private: 42 | std::multimap changed_callbacks; 43 | 44 | public: 45 | virtual ~RenderTarget() = default; 46 | 47 | void AddChangedCallback(ChangedCallbackOrder order, ChangedCallback *callback); 48 | void RemoveChangedCallback(ChangedCallback *callback); 49 | 50 | virtual vk::Extent2D GetExtent() const =0; 51 | 52 | protected: 53 | void SignalChangedCallbacks(); 54 | }; 55 | 56 | 57 | /** 58 | * A {@link RenderTarget} to render color into, e.g. a {@link Swapchain}. 59 | */ 60 | class ColorRenderTarget : public RenderTarget 61 | { 62 | public: 63 | ~ColorRenderTarget() override = default; 64 | virtual vk::Format GetFormat() const =0; 65 | virtual std::vector GetImageViews() const =0; 66 | }; 67 | 68 | 69 | /** 70 | * A {@link RenderTarget} to render depth into. 71 | */ 72 | class DepthRenderTarget : public RenderTarget 73 | { 74 | public: 75 | ~DepthRenderTarget() override = default; 76 | virtual vk::Format GetFormat() const =0; 77 | virtual vk::ImageView GetImageView() const =0; 78 | }; 79 | 80 | 81 | /** 82 | * A {@link DepthRenderTarget} that is associated with a {@link ColorRenderTarget} 83 | * and manages the creation of its resources automatically. 84 | */ 85 | class ManagedDepthRenderTarget : public DepthRenderTarget, RenderTarget::ChangedCallback 86 | { 87 | private: 88 | Engine * const engine; 89 | ColorRenderTarget * const color_render_target; 90 | 91 | vk::Format format; 92 | lavos::Image image; 93 | vk::ImageView image_view; 94 | 95 | void CreateResources(); 96 | void CleanupResources(); 97 | 98 | protected: 99 | void RenderTargetChanged(RenderTarget *render_target) override; 100 | 101 | public: 102 | ManagedDepthRenderTarget(Engine *engine, ColorRenderTarget *color_render_target); 103 | ~ManagedDepthRenderTarget() override; 104 | 105 | vk::Extent2D GetExtent() const override { return color_render_target->GetExtent(); } 106 | vk::Format GetFormat() const override { return format; } 107 | vk::ImageView GetImageView() const override { return image_view; } 108 | }; 109 | 110 | 111 | } 112 | 113 | #endif //LAVOS_RENDER_TARGET_H 114 | -------------------------------------------------------------------------------- /lavos/include/lavos/node.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef LAVOS_NODE_H 3 | #define LAVOS_NODE_H 4 | 5 | #include 6 | #include 7 | 8 | #include "component/component.h" 9 | 10 | namespace lavos 11 | { 12 | 13 | class TransformComp; 14 | 15 | class Node 16 | { 17 | friend class Scene; 18 | 19 | private: 20 | bool is_root = false; 21 | Node *parent = nullptr; 22 | 23 | std::vector components; 24 | std::vector children; 25 | 26 | TransformComp *transform_component = nullptr; 27 | 28 | public: 29 | Node(); 30 | ~Node(); 31 | 32 | template 33 | T *GetComponent() const; 34 | 35 | template 36 | std::vector GetComponents() const; 37 | 38 | template 39 | T *GetComponentInChildren() const; 40 | 41 | template 42 | std::vector GetComponentsInChildren() const; 43 | 44 | TransformComp *GetTransformComp() const { return transform_component; } 45 | 46 | 47 | const std::vector &GetChildren() const { return children; } 48 | 49 | Node *GetParent() const { return parent; } 50 | 51 | void AddComponent(Component *component); 52 | void RemoveComponent(Component *component); 53 | 54 | void AddChild(Node *node); 55 | void RemoveChild(Node *node); 56 | 57 | void TraversePreOrder(std::function func); 58 | void TraversePostOrder(std::function func); 59 | 60 | void Update(float delta_time) 61 | { 62 | for(auto component : components) 63 | component->Update(delta_time); 64 | 65 | for(auto child : children) 66 | child->Update(delta_time); 67 | } 68 | }; 69 | 70 | 71 | template 72 | inline T *Node::GetComponent() const 73 | { 74 | for(auto component: components) 75 | { 76 | auto found_component = dynamic_cast(component); 77 | if(found_component != nullptr) 78 | return found_component; 79 | } 80 | 81 | return nullptr; 82 | } 83 | 84 | template 85 | inline std::vector Node::GetComponents() const 86 | { 87 | std::vector r; 88 | 89 | for(auto component: components) 90 | { 91 | auto found_component = dynamic_cast(component); 92 | if(found_component != nullptr) 93 | r.push_back(found_component); 94 | } 95 | 96 | return r; 97 | } 98 | 99 | template 100 | inline T *Node::GetComponentInChildren() const 101 | { 102 | auto found_component = GetComponent(); 103 | if(found_component != nullptr) 104 | return found_component; 105 | 106 | for(auto child: children) 107 | { 108 | found_component = child->GetComponentInChildren(); 109 | if(found_component != nullptr) 110 | return found_component; 111 | } 112 | 113 | return nullptr; 114 | } 115 | 116 | template 117 | inline std::vector Node::GetComponentsInChildren() const 118 | { 119 | std::vector r = GetComponents(); 120 | 121 | for(auto child: children) 122 | { 123 | auto child_components = child->GetComponentsInChildren(); 124 | r.insert(r.end(), child_components.begin(), child_components.end()); 125 | } 126 | 127 | return r; 128 | } 129 | 130 | } 131 | 132 | 133 | #endif //VULKAN_NODE_H 134 | -------------------------------------------------------------------------------- /lavos/include/lavos/component/camera.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef LAVOS_CAMERA_H 3 | #define LAVOS_CAMERA_H 4 | 5 | #include "component.h" 6 | #include "transform_component.h" 7 | #include "../node.h" 8 | 9 | #include "../glm_config.h" 10 | #include 11 | #include 12 | 13 | #include 14 | 15 | namespace lavos 16 | { 17 | 18 | class Camera: public Component 19 | { 20 | public: 21 | enum class Type { PERSPECTIVE, ORTHOGRAPHIC } ; 22 | 23 | private: 24 | Type type = Type::PERSPECTIVE; 25 | 26 | glm::vec3 up_vector = glm::vec3(0.0f, 1.0f, 0.0f); 27 | 28 | float near_clip = 0.1f; 29 | float far_clip = 100.0f; 30 | 31 | float perspective_fovy = glm::radians(60.0f); 32 | float perspective_aspect = 1.0f; 33 | 34 | float orthographic_left = -1.0f; 35 | float orthographic_right = 1.0f; 36 | float orthographic_bottom = -1.0f; 37 | float orthographic_top = 1.0f; 38 | 39 | public: 40 | Type GetType() const { return type; } 41 | void SetType(Type type) { this->type = type; } 42 | 43 | glm::vec3 GetUpVector() const { return up_vector; } 44 | void SetUpVector(const glm::vec3 &v) { up_vector = v; } 45 | 46 | float GetNearClip() const { return near_clip; } 47 | void SetNearClip(float near_clip) { this->near_clip = near_clip; } 48 | 49 | float GetFarClip() const { return far_clip; } 50 | void SetFarClip(float far_clip) { this->far_clip = far_clip; } 51 | 52 | float GetPerspectiveFovY() const { return perspective_fovy; } 53 | void SetPerspectiveFovY(float fovy) { this->perspective_fovy = fovy; } 54 | 55 | float GetPerspectiveAspect() const { return perspective_aspect; } 56 | void SetPerspectiveAspect(float aspect) { perspective_aspect = aspect; } 57 | 58 | float GetOrthographicLeft() const { return orthographic_left; } 59 | float GetOrthographicRight() const { return orthographic_right; } 60 | float GetOrthographicBottom() const { return orthographic_bottom; } 61 | float GetOrthographicTop() const { return orthographic_top; } 62 | 63 | void SetPerspectiveParams(float fovy, float aspect) 64 | { this->perspective_fovy = fovy; this->perspective_aspect = aspect; } 65 | 66 | void SetOrthographicParams(float left, float right, float bottom, float top) 67 | { this->orthographic_left = left; this->orthographic_right = right; this->orthographic_bottom = bottom; this->orthographic_top = top; } 68 | 69 | 70 | glm::mat4 GetModelViewMatrix() 71 | { 72 | auto transform_component = GetNode()->GetTransformComp(); 73 | if(transform_component == nullptr) 74 | throw std::runtime_error("node with a camera component does not have a transform component."); 75 | 76 | glm::mat4 transform_mat = transform_component->GetMatrixWorld(); 77 | return glm::inverse(transform_mat); 78 | } 79 | 80 | glm::mat4 GetProjectionMatrix() 81 | { 82 | if(type == Type::PERSPECTIVE) 83 | { 84 | return glm::perspective(perspective_fovy, perspective_aspect, near_clip, far_clip); 85 | } 86 | else // ORTHOGRAPHIC 87 | { 88 | return glm::ortho(orthographic_left, orthographic_right, orthographic_bottom, orthographic_top, 89 | near_clip, far_clip); 90 | } 91 | } 92 | }; 93 | 94 | } 95 | 96 | #endif //VULKAN_CAMERA_COMPONENT_H 97 | -------------------------------------------------------------------------------- /lavos/cmake/ShaderResources.cmake: -------------------------------------------------------------------------------- 1 | 2 | include(ResourceGenerator) 3 | 4 | find_package(Shaderc REQUIRED) 5 | 6 | function(parse_make_deps OUTPUT_VAR MAKE_DEPS) 7 | if("${MAKE_DEPS}" MATCHES "^[^:]+:*(.*)$") 8 | string(STRIP "${CMAKE_MATCH_1}" DEPS) 9 | string(REPLACE " " ";" DEPS "${DEPS}") 10 | set("${OUTPUT_VAR}" "${DEPS}" PARENT_SCOPE) 11 | else() 12 | set("${OUTPUT_VAR}" "" PARENT_SCOPE) 13 | endif() 14 | endfunction() 15 | 16 | function(compile_spirv) 17 | cmake_parse_arguments(ARG "" "SPIRV_FILE;GLSL_FILE" "GLSLC_FLAGS" ${ARGN}) 18 | execute_process(COMMAND "${Shaderc_GLSLC}" -x glsl ${ARG_GLSLC_FLAGS} -M "${ARG_GLSL_FILE}" 19 | OUTPUT_VARIABLE GLSL_MAKE_DEPS) 20 | parse_make_deps(GLSL_DEPS "${GLSL_MAKE_DEPS}") 21 | 22 | add_custom_command(OUTPUT "${spirv_file_abs}" 23 | COMMAND "${Shaderc_GLSLC}" ${ARG_GLSLC_FLAGS} -x glsl "${ARG_GLSL_FILE}" -o "${ARG_SPIRV_FILE}" 24 | MAIN_DEPENDENCY "${ARG_GLSL_FILE}" 25 | DEPENDS ${GLSL_DEPS}) 26 | endfunction() 27 | 28 | function(add_spirv_shaders) 29 | cmake_parse_arguments(ARG "" "TARGET_DIR;BASE_DIR;VAR" "" ${ARGN}) 30 | if(NOT ARG_TARGET_DIR) 31 | message(FATAL_ERROR "add_spirv_shaders: No TARGET_DIR given.") 32 | endif() 33 | if(NOT ARG_VAR) 34 | message(FATAL_ERROR "add_spirv_shaders: No VAR given.") 35 | endif() 36 | if(NOT ARG_BASE_DIR) 37 | message("BASE_DIR not given") 38 | set(ARG_BASE_DIR "${CMAKE_CURRENT_SOURCE_DIR}") 39 | endif() 40 | set(glsl_files "${ARG_UNPARSED_ARGUMENTS}") 41 | 42 | set(${spirv_files} "") 43 | foreach(glsl_file ${glsl_files}) 44 | if(IS_ABSOLUTE "${glsl_file}") 45 | file(RELATIVE_PATH glsl_file "${ARG_BASE_DIR}" "${glsl_file}") 46 | endif() 47 | set(glsl_file_abs "${ARG_BASE_DIR}/${glsl_file}") 48 | 49 | get_filename_component(spirv_file_dir "${ARG_TARGET_DIR}/${glsl_file}" DIRECTORY) 50 | file(MAKE_DIRECTORY "${spirv_file_dir}") 51 | 52 | if(glsl_file MATCHES "(.+)\\.([vf]+)\\.shader") 53 | # compile stuff like "filename.vf.shader" to "filename.vert.spv" and "filename.frag.spv" 54 | # with defines SHADER_VERTEX or SHADER_FRAGMENT respectively 55 | 56 | set(file_base_name "${CMAKE_MATCH_1}") 57 | set(file_stage_chars "${CMAKE_MATCH_2}") 58 | 59 | set(STAGES 60 | v VERT vert 61 | f FRAG frag) 62 | 63 | foreach(i RANGE 0 3 3) 64 | list(GET STAGES "${i}+0" stage_char) 65 | math(EXPR i "${i}+1") 66 | list(GET STAGES "${i}+1" stage_define) 67 | math(EXPR i "${i}+1") 68 | list(GET STAGES "${i}+2" stage_name) 69 | if(NOT "${file_stage_chars}" MATCHES ".*${stage_char}.*") 70 | continue() 71 | endif() 72 | 73 | set(spirv_file_abs "${ARG_TARGET_DIR}/${file_base_name}.${stage_name}.spv") 74 | list(APPEND spirv_files "${spirv_file_abs}") 75 | compile_spirv( 76 | SPIRV_FILE "${spirv_file_abs}" 77 | GLSL_FILE "${glsl_file_abs}" 78 | GLSLC_FLAGS "-DSHADER_${stage_define}=1" "-fshader-stage=${stage_name}") 79 | endforeach() 80 | 81 | else() 82 | # otherwise just compile "filename.abc" to "filename.abc.spv" 83 | set(spirv_file_abs "${ARG_TARGET_DIR}/${glsl_file}.spv") 84 | list(APPEND spirv_files "${spirv_file_abs}") 85 | compile_spirv( 86 | SPIRV_FILE "${spirv_file_abs}" 87 | GLSL_FILE "${glsl_file_abs}") 88 | endif() 89 | endforeach() 90 | set("${ARG_VAR}" "${spirv_files}" PARENT_SCOPE) 91 | endfunction() -------------------------------------------------------------------------------- /demos/gltf/gltf.cpp: -------------------------------------------------------------------------------- 1 | 2 | #if defined(__ANDROID__) 3 | #include 4 | #endif 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include 21 | 22 | 23 | lavos::shell::glfw::WindowApplication *app = nullptr; 24 | 25 | lavos::Renderer *renderer = nullptr; 26 | lavos::Material *material; 27 | 28 | lavos::AssetContainer *asset_container = nullptr; 29 | 30 | lavos::MaterialInstance *material_instance; 31 | 32 | lavos::Scene *scene; 33 | 34 | double last_cursor_x, last_cursor_y; 35 | lavos::FirstPersonController *fp_controller; 36 | 37 | 38 | void Init(std::string gltf_filename) 39 | { 40 | material = new lavos::PhongMaterial(app->GetEngine()); 41 | 42 | auto render_config = lavos::RenderConfigBuilder().Build(); 43 | 44 | renderer = new lavos::Renderer(app->GetEngine(), render_config, app->GetSwapchain(), app->GetDepthRenderTarget()); 45 | renderer->AddMaterial(material); 46 | 47 | asset_container = lavos::AssetContainer::LoadFromGLTF(app->GetEngine(), render_config, material, gltf_filename); 48 | 49 | lavos::Scene *scene = asset_container->scenes[0]; 50 | scene->SetAmbientLightIntensity(glm::vec3(0.3f, 0.3f, 0.3f)); 51 | 52 | renderer->SetScene(scene); 53 | 54 | lavos::Camera *camera = scene->GetRootNode()->GetComponentInChildren(); 55 | 56 | if(camera == nullptr) 57 | { 58 | lavos::Node *camera_node = new lavos::Node(); 59 | scene->GetRootNode()->AddChild(camera_node); 60 | 61 | camera_node->AddComponent(new lavos::TransformComp()); 62 | 63 | camera_node->GetTransformComp()->translation = glm::vec3(5.0f, 5.0f, 5.0f); 64 | camera_node->GetTransformComp()->SetLookAt(glm::vec3(0.0f, 0.0f, 0.0f)); 65 | 66 | camera = new lavos::Camera(); 67 | camera->SetNearClip(0.01f); 68 | camera_node->AddComponent(camera); 69 | } 70 | 71 | lavos::Node *light_node = new lavos::Node(); 72 | scene->GetRootNode()->AddChild(light_node); 73 | 74 | light_node->AddComponent(new lavos::TransformComp()); 75 | light_node->GetTransformComp()->SetLookAt(glm::vec3(-1.0f, -1.0f, -1.0f)); 76 | 77 | lavos::DirectionalLight *light = new lavos::DirectionalLight(); 78 | light_node->AddComponent(light); 79 | 80 | renderer->SetCamera(camera); 81 | 82 | material_instance = asset_container->material_instances.front(); 83 | } 84 | 85 | void Cleanup() 86 | { 87 | delete asset_container; 88 | delete renderer; 89 | delete material; 90 | delete app; 91 | } 92 | 93 | int main(int argc, const char **argv) 94 | { 95 | std::string gltf_filename = "data/gltftest.gltf"; 96 | if(argc > 1) 97 | gltf_filename = argv[1]; 98 | 99 | app = new lavos::shell::glfw::WindowApplication(800, 600, "GLTF", true); 100 | 101 | Init(gltf_filename); 102 | 103 | while(true) 104 | { 105 | app->BeginFrame(); 106 | app->Update(); 107 | 108 | if(glfwWindowShouldClose(app->GetWindow())) 109 | break; 110 | 111 | app->Render(renderer); 112 | app->EndFrame(); 113 | } 114 | 115 | Cleanup(); 116 | 117 | return EXIT_SUCCESS; 118 | } -------------------------------------------------------------------------------- /demos/qt_qvulkanwindow/mainwindow.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef VULKAN_MAINWINDOW_H 3 | #define VULKAN_MAINWINDOW_H 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | class QVulkanWindowColorRenderTarget : public lavos::ColorRenderTarget 14 | { 15 | private: 16 | QVulkanWindow * const vulkan_window; 17 | 18 | public: 19 | explicit QVulkanWindowColorRenderTarget(QVulkanWindow * const vulkan_window) 20 | : vulkan_window(vulkan_window) {} 21 | 22 | vk::Extent2D GetExtent() const override 23 | { 24 | auto size = vulkan_window->swapChainImageSize(); 25 | return vk::Extent2D(static_cast(size.width()), 26 | static_cast(size.height())); 27 | } 28 | 29 | vk::Format GetFormat() const override 30 | { 31 | return vk::Format(vulkan_window->colorFormat()); 32 | } 33 | 34 | std::vector GetImageViews() const override 35 | { 36 | int count = vulkan_window->swapChainImageCount(); 37 | std::vector ret(static_cast(count)); 38 | for (int i=0; iswapChainImageView(i); 41 | } 42 | return ret; 43 | } 44 | 45 | void SwapchainChanged() 46 | { 47 | SignalChangedCallbacks(); 48 | } 49 | }; 50 | 51 | class QVulkanWindowDepthRenderTarget : public lavos::DepthRenderTarget 52 | { 53 | private: 54 | QVulkanWindow * const vulkan_window; 55 | 56 | public: 57 | explicit QVulkanWindowDepthRenderTarget(QVulkanWindow * const vulkan_window) 58 | : vulkan_window(vulkan_window) {} 59 | 60 | vk::Extent2D GetExtent() const override 61 | { 62 | auto size = vulkan_window->swapChainImageSize(); 63 | return vk::Extent2D(static_cast(size.width()), 64 | static_cast(size.height())); 65 | } 66 | 67 | vk::Format GetFormat() const override 68 | { 69 | return vk::Format(vulkan_window->depthStencilFormat()); 70 | } 71 | 72 | vk::ImageView GetImageView() const override 73 | { 74 | return vulkan_window->depthStencilImageView(); 75 | } 76 | }; 77 | 78 | class MainWindowRenderer: public QVulkanWindowRenderer 79 | { 80 | private: 81 | lavos::Engine *engine = nullptr; 82 | QVulkanWindow *window; 83 | 84 | lavos::RenderConfig render_config; 85 | 86 | lavos::PhongMaterial *material = nullptr; 87 | lavos::Scene *scene = nullptr; 88 | lavos::Camera *camera = nullptr; 89 | 90 | QVulkanWindowColorRenderTarget *color_render_target = nullptr; 91 | QVulkanWindowDepthRenderTarget *depth_render_target = nullptr; 92 | lavos::Renderer *renderer = nullptr; 93 | 94 | lavos::AssetContainer *asset_container = nullptr; 95 | 96 | public: 97 | MainWindowRenderer(lavos::Engine *engine, QVulkanWindow *window) 98 | : engine(engine), window(window) {} 99 | 100 | void initResources() override; 101 | void initSwapChainResources() override; 102 | void releaseSwapChainResources() override; 103 | void releaseResources() override; 104 | 105 | void startNextFrame() override; 106 | }; 107 | 108 | class MainWindow: public QVulkanWindow 109 | { 110 | Q_OBJECT 111 | 112 | private: 113 | lavos::Engine *engine; 114 | 115 | public: 116 | MainWindow(lavos::Engine *engine, QWindow *parent = nullptr) 117 | : QVulkanWindow(parent), engine(engine) {} 118 | 119 | QVulkanWindowRenderer *createRenderer() override 120 | { 121 | return new MainWindowRenderer(engine, this); 122 | } 123 | 124 | }; 125 | 126 | #endif //VULKAN_MAINWINDOW_H 127 | -------------------------------------------------------------------------------- /lavos/include/lavos/material/material.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef LAVOS_MATERIAL_H 3 | #define LAVOS_MATERIAL_H 4 | 5 | #include 6 | 7 | #include 8 | 9 | #include "../texture.h" 10 | #include "../buffer.h" 11 | 12 | namespace lavos 13 | { 14 | 15 | class Engine; 16 | class MaterialInstance; 17 | 18 | /** 19 | * Describes one type of Material with shaders and some Material-specific settings 20 | * used to build a Vulkan Pipeline. 21 | * 22 | * This is not a material in the sense of a collection of settings and textures, but only 23 | * the type of material, e.g. Phong, PBR, etc. 24 | * The actual settings are defined by a MaterialInstance. 25 | */ 26 | class Material 27 | { 28 | public: 29 | /** 30 | * Mode in which a Material can be rendered, e.g. default forward or shadow. 31 | * See DefaultRenderMode for builtin values. 32 | */ 33 | using RenderMode = int; 34 | 35 | /** 36 | * Builtin values for RenderMode. 37 | * Custom modes can start from DefaultRenderMode::User0. 38 | */ 39 | enum DefaultRenderMode : RenderMode { 40 | ColorForward = 0, 41 | Shadow, 42 | User0 43 | }; 44 | 45 | using DescriptorSetId = int; 46 | using InstanceDataId = int; 47 | 48 | using TextureSlot = unsigned int; 49 | using ParameterSlot = unsigned int; 50 | 51 | static const TextureSlot texture_slot_base_color = 0; 52 | static const TextureSlot texture_slot_normal = 1; 53 | 54 | static const ParameterSlot parameter_slot_base_color_factor = 0; 55 | 56 | struct DescriptorSetLayout 57 | { 58 | vk::DescriptorSetLayout layout; 59 | std::vector pool_sizes; 60 | }; 61 | 62 | private: 63 | std::map descriptor_set_layouts; 64 | 65 | protected: 66 | Engine *engine; 67 | 68 | void CreateDescriptorSetLayout(DescriptorSetId id, const std::vector &bindings); 69 | 70 | struct UBOInstanceData 71 | { 72 | lavos::Buffer *uniform_buffer; 73 | 74 | UBOInstanceData(lavos::Buffer *uniform_buffer); 75 | ~UBOInstanceData(); 76 | }; 77 | 78 | public: 79 | Material(Engine *engine); 80 | virtual ~Material(); 81 | 82 | Engine *GetEngine() const { return engine; } 83 | 84 | const DescriptorSetLayout *GetDescriptorSetLayout(DescriptorSetId id) const; 85 | 86 | virtual bool GetRenderModeSupport(RenderMode render_mode) const =0; 87 | 88 | virtual std::vector GetShaderStageCreateInfos(RenderMode render_mode) const =0; 89 | 90 | virtual DescriptorSetId GetDescriptorSetId(RenderMode render_mode) const { return render_mode; }; 91 | virtual void WriteDescriptorSet(DescriptorSetId id, vk::DescriptorSet descriptor_set, MaterialInstance *instance) =0; 92 | 93 | virtual InstanceDataId GetInstanceDataId(RenderMode render_mode) { return render_mode; } 94 | virtual void *CreateInstanceData(InstanceDataId id) { return nullptr; } 95 | virtual void DestroyInstanceData(InstanceDataId id, void *data) {} 96 | virtual void UpdateInstanceData(InstanceDataId id, void *data, MaterialInstance *instance) {} 97 | 98 | static vk::ShaderModule CreateShaderModule(vk::Device device, std::string shader); 99 | 100 | virtual Texture GetTextureDefaultImage() const { return nullptr; }; 101 | 102 | 103 | virtual vk::PrimitiveTopology GetPrimitiveTopology() { return vk::PrimitiveTopology::eTriangleList; } 104 | 105 | virtual std::vector GetVertexInputBindingDescriptions(); 106 | virtual std::vector GetVertexInputAttributeDescriptions(); 107 | }; 108 | 109 | } 110 | 111 | #endif //VULKAN_MATERIAL_H 112 | -------------------------------------------------------------------------------- /demos/point_cloud/point_cloud.cpp: -------------------------------------------------------------------------------- 1 | 2 | #if defined(__ANDROID__) 3 | #include 4 | #endif 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include 21 | 22 | #include 23 | #include 24 | 25 | 26 | lavos::shell::glfw::WindowApplication *app = nullptr; 27 | 28 | lavos::Renderer *renderer = nullptr; 29 | lavos::Material *material; 30 | 31 | lavos::PointCloud *point_cloud = nullptr; 32 | 33 | lavos::MaterialInstance *material_instance; 34 | 35 | lavos::Scene *scene; 36 | 37 | double last_cursor_x, last_cursor_y; 38 | lavos::FirstPersonControllerComponent *fp_controller; 39 | 40 | 41 | void Init() 42 | { 43 | material = new lavos::PointCloudMaterial(app->GetEngine()); 44 | 45 | auto render_config = lavos::RenderConfigBuilder().Build(); 46 | 47 | renderer = new lavos::Renderer(app->GetEngine(), render_config, app->GetSwapchain(), app->GetDepthRenderTarget()); 48 | renderer->AddMaterial(material); 49 | 50 | scene = new lavos::Scene(); 51 | 52 | renderer->SetScene(scene); 53 | 54 | pcl::PointCloud::Ptr pcl_cloud(new pcl::PointCloud); 55 | if(pcl::io::loadPCDFile("data/lamppost.pcd", *pcl_cloud) == -1) 56 | { 57 | throw std::runtime_error("Failed to load point cloud."); 58 | } 59 | 60 | point_cloud = new lavos::PointCloud(app->GetEngine()); 61 | auto point_cloud_size = (*pcl_cloud).size(); 62 | point_cloud->points.resize(point_cloud_size); 63 | for(size_t i=0; ipoints[i] = glm::vec3(pcl_point.x, pcl_point.y, pcl_point.z); 67 | } 68 | point_cloud->CreateBuffers(); 69 | 70 | auto *point_cloud_node = new lavos::Node(); 71 | point_cloud_node->AddComponent(new lavos::TransformComponent()); 72 | scene->GetRootNode()->AddChild(point_cloud_node); 73 | 74 | auto *point_cloud_component = new lavos::PointCloudComponent(point_cloud); 75 | point_cloud_node->AddComponent(point_cloud_component); 76 | 77 | 78 | auto *camera_node = new lavos::Node(); 79 | scene->GetRootNode()->AddChild(camera_node); 80 | 81 | camera_node->AddComponent(new lavos::TransformComponent()); 82 | 83 | camera_node->GetTransformComponent()->translation = glm::vec3(-8.0f, 5.0f, -3.0f); 84 | camera_node->GetTransformComponent()->SetLookAt(glm::vec3(-10.0f, 0.0f, -3.0f)); 85 | 86 | auto *camera = new lavos::CameraComponent(); 87 | camera->SetNearClip(0.01f); 88 | camera_node->AddComponent(camera); 89 | 90 | 91 | auto *light_node = new lavos::Node(); 92 | scene->GetRootNode()->AddChild(light_node); 93 | 94 | light_node->AddComponent(new lavos::TransformComponent()); 95 | light_node->GetTransformComponent()->SetLookAt(glm::vec3(-1.0f, -1.0f, -1.0f)); 96 | 97 | lavos::DirectionalLightComponent *light = new lavos::DirectionalLightComponent(); 98 | light_node->AddComponent(light); 99 | 100 | 101 | renderer->SetCamera(camera); 102 | } 103 | 104 | void Cleanup() 105 | { 106 | delete renderer; 107 | delete scene; 108 | delete point_cloud; 109 | delete material; 110 | delete app; 111 | } 112 | 113 | int main(int argc, const char **argv) 114 | { 115 | app = new lavos::shell::glfw::WindowApplication(800, 600, "Point Cloud", true); 116 | 117 | Init(); 118 | 119 | while(true) 120 | { 121 | app->BeginFrame(); 122 | app->Update(); 123 | 124 | if(glfwWindowShouldClose(app->GetWindow())) 125 | break; 126 | 127 | app->Render(renderer); 128 | app->EndFrame(); 129 | } 130 | 131 | Cleanup(); 132 | 133 | return EXIT_SUCCESS; 134 | } -------------------------------------------------------------------------------- /android/gltf/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 12 | 17 | 22 | 27 | 32 | 37 | 42 | 47 | 52 | 57 | 62 | 67 | 72 | 77 | 82 | 87 | 92 | 97 | 102 | 107 | 112 | 113 | 114 | -------------------------------------------------------------------------------- /android/common/android_common.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include "android_common.h" 6 | 7 | static android_app *app; 8 | 9 | 10 | // Helper class to forward the cout/cerr output to logcat derived from: 11 | // http://stackoverflow.com/questions/8870174/is-stdcout-usable-in-android-ndk 12 | class AndroidBuffer : public std::streambuf 13 | { 14 | public: 15 | AndroidBuffer(android_LogPriority priority) 16 | { 17 | priority_ = priority; 18 | this->setp(buffer_, buffer_ + kBufferSize - 1); 19 | } 20 | 21 | private: 22 | static const int32_t kBufferSize = 128; 23 | int32_t overflow(int32_t c) 24 | { 25 | if (c == traits_type::eof()) 26 | { 27 | *this->pptr() = traits_type::to_char_type(c); 28 | this->sbumpc(); 29 | } 30 | return this->sync() ? traits_type::eof() : traits_type::not_eof(c); 31 | } 32 | 33 | int32_t sync() 34 | { 35 | int32_t rc = 0; 36 | if (this->pbase() != this->pptr()) 37 | { 38 | char writebuf[kBufferSize + 1]; 39 | memcpy(writebuf, this->pbase(), this->pptr() - this->pbase()); 40 | writebuf[this->pptr() - this->pbase()] = '\0'; 41 | 42 | rc = __android_log_write(priority_, "std", writebuf) > 0; 43 | this->setp(buffer_, buffer_ + kBufferSize - 1); 44 | } 45 | return rc; 46 | } 47 | 48 | android_LogPriority priority_ = ANDROID_LOG_INFO; 49 | char buffer_[kBufferSize]; 50 | }; 51 | 52 | 53 | void AndroidSetApp(android_app *_app) 54 | { 55 | app = _app; 56 | } 57 | 58 | ANativeWindow *AndroidGetApplicationWindow() 59 | { 60 | assert(app != nullptr); 61 | return app->window; 62 | } 63 | 64 | void AndroidGetWindowSize(int32_t *width, int32_t *height) 65 | { 66 | assert(app != nullptr); 67 | *width = ANativeWindow_getWidth(app->window); 68 | *height = ANativeWindow_getHeight(app->window); 69 | } 70 | 71 | std::vector AndroidReadSPIRVShader(const std::string shader) 72 | { 73 | std::string filename = "shader/" + shader + ".spv"; 74 | return AndroidReadAssetBinary(filename); 75 | } 76 | 77 | std::vector AndroidReadAssetBinary(const std::string filename) 78 | { 79 | assert(app != nullptr); 80 | 81 | AAsset *asset = AAssetManager_open(app->activity->assetManager, filename.c_str(), AASSET_MODE_BUFFER); 82 | 83 | if(!asset) 84 | throw std::runtime_error("failed to open asset for filename " + filename); 85 | 86 | std::vector buffer(static_cast(AAsset_getLength(asset))); 87 | const void *asset_buffer = AAsset_getBuffer(asset); 88 | 89 | if(asset_buffer) 90 | memcpy(buffer.data(), asset_buffer, buffer.size()); 91 | else 92 | { 93 | AAsset_close(asset); 94 | throw std::runtime_error("failed to read asset for filename " + filename); 95 | } 96 | 97 | AAsset_close(asset); 98 | 99 | return buffer; 100 | } 101 | 102 | void Android_handle_cmd(android_app *app, int32_t cmd) 103 | { 104 | switch (cmd) 105 | { 106 | case APP_CMD_INIT_WINDOW: 107 | sample_main(); 108 | LOGI("\n"); 109 | LOGI("================================================="); 110 | LOGI(" The sample ran successfully!!"); 111 | LOGI("================================================="); 112 | LOGI("\n"); 113 | break; 114 | case APP_CMD_TERM_WINDOW: 115 | // The window is being hidden or closed, clean it up. 116 | break; 117 | default: 118 | LOGI("event not handled: %d", cmd); 119 | } 120 | } 121 | 122 | 123 | bool Android_process_command() 124 | { 125 | assert(app != nullptr); 126 | int events; 127 | android_poll_source *source; 128 | // Poll all pending events. 129 | if (ALooper_pollAll(0, NULL, &events, (void **)&source) >= 0) { 130 | // Process each polled events 131 | if (source != NULL) source->process(app, source); 132 | } 133 | return app->destroyRequested; 134 | } 135 | 136 | 137 | extern "C" void android_main(struct android_app *state) 138 | { 139 | AndroidSetApp(state); 140 | 141 | // Set the callback to process system events 142 | app->onAppCmd = Android_handle_cmd; 143 | 144 | // Forward cout/cerr to logcat. 145 | std::cout.rdbuf(new AndroidBuffer(ANDROID_LOG_INFO)); 146 | std::cerr.rdbuf(new AndroidBuffer(ANDROID_LOG_ERROR)); 147 | 148 | // Main loop 149 | do { 150 | Android_process_command(); 151 | } // Check if system requested to quit the application 152 | while (app->destroyRequested == 0); 153 | 154 | //sample_main(); 155 | } -------------------------------------------------------------------------------- /lavos/src/material/gouraud_material.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "lavos/engine.h" 3 | #include "lavos/material/gouraud_material.h" 4 | #include "lavos/material/material_instance.h" 5 | 6 | #include "lavos/shader_load.h" 7 | 8 | using namespace lavos; 9 | 10 | GouraudMaterial::GouraudMaterial(lavos::Engine *engine) : Material(engine) 11 | { 12 | CreateDescriptorSetLayouts(); 13 | 14 | vert_shader_module = CreateShaderModule(engine->GetVkDevice(), "material/gouraud.vert"); 15 | frag_shader_module = CreateShaderModule(engine->GetVkDevice(), "material/gouraud.frag"); 16 | 17 | texture_default_base_color = Texture::CreateColor(engine, vk::Format::eR8G8B8Unorm, glm::vec4(1.0f, 1.0f, 1.0f, 0.0f)); 18 | texture_default_normal = Texture::CreateColor(engine, vk::Format::eR8G8B8Unorm, glm::vec4(0.5f, 0.5f, 1.0f, 0.0f)); 19 | } 20 | 21 | GouraudMaterial::~GouraudMaterial() 22 | { 23 | auto &device = engine->GetVkDevice(); 24 | 25 | engine->DestroyTexture(texture_default_base_color); 26 | engine->DestroyTexture(texture_default_normal); 27 | 28 | device.destroyShaderModule(vert_shader_module); 29 | device.destroyShaderModule(frag_shader_module); 30 | } 31 | 32 | void GouraudMaterial::CreateDescriptorSetLayouts() 33 | { 34 | // TODO: how did this even work? 35 | // descriptor_set_layout = nullptr; 36 | } 37 | 38 | std::vector GouraudMaterial::GetShaderStageCreateInfos(Material::RenderMode render_mode) const 39 | { 40 | return { 41 | vk::PipelineShaderStageCreateInfo(vk::PipelineShaderStageCreateFlags(), 42 | vk::ShaderStageFlagBits::eVertex, 43 | vert_shader_module, 44 | "main"), 45 | vk::PipelineShaderStageCreateInfo(vk::PipelineShaderStageCreateFlags(), 46 | vk::ShaderStageFlagBits::eFragment, 47 | frag_shader_module, 48 | "main") 49 | }; 50 | } 51 | 52 | 53 | void GouraudMaterial::WriteDescriptorSet(Material::DescriptorSetId id, vk::DescriptorSet descriptor_set, MaterialInstance *instance) 54 | { 55 | auto instance_data = reinterpret_cast(instance->GetInstanceData(id)); 56 | 57 | auto ubo_info = vk::DescriptorBufferInfo() 58 | .setBuffer(instance_data->uniform_buffer->GetVkBuffer()) 59 | .setOffset(0) 60 | .setRange(sizeof(UniformBuffer)); 61 | 62 | auto ubo_write = vk::WriteDescriptorSet() 63 | .setDstSet(descriptor_set) 64 | .setDstBinding(0) 65 | .setDstArrayElement(0) 66 | .setDescriptorType(vk::DescriptorType::eUniformBuffer) 67 | .setDescriptorCount(1) 68 | .setPBufferInfo(&ubo_info); 69 | 70 | 71 | 72 | Texture *base_color_texture = instance->GetTexture(texture_slot_base_color); 73 | if(base_color_texture == nullptr) 74 | base_color_texture = &texture_default_base_color; 75 | 76 | auto base_color_image_info = vk::DescriptorImageInfo() 77 | .setImageLayout(vk::ImageLayout::eShaderReadOnlyOptimal) 78 | .setImageView(base_color_texture->image_view) 79 | .setSampler(base_color_texture->sampler); 80 | 81 | auto base_color_texture_write = vk::WriteDescriptorSet() 82 | .setDstSet(descriptor_set) 83 | .setDstBinding(1) 84 | .setDstArrayElement(0) 85 | .setDescriptorType(vk::DescriptorType::eCombinedImageSampler) 86 | .setDescriptorCount(1) 87 | .setPImageInfo(&base_color_image_info); 88 | 89 | 90 | engine->GetVkDevice().updateDescriptorSets({base_color_texture_write, ubo_write}, nullptr); 91 | } 92 | 93 | 94 | void *GouraudMaterial::CreateInstanceData(InstanceDataId id) 95 | { 96 | auto buffer = engine->CreateBuffer(sizeof(UniformBuffer), 97 | vk::BufferUsageFlagBits::eUniformBuffer, 98 | VMA_MEMORY_USAGE_CPU_ONLY); 99 | 100 | return new UBOInstanceData(buffer); 101 | } 102 | 103 | void GouraudMaterial::DestroyInstanceData(InstanceDataId id, void *data_p) 104 | { 105 | auto data = reinterpret_cast(data_p); 106 | delete data; 107 | } 108 | 109 | void GouraudMaterial::UpdateInstanceData(InstanceDataId id, void *data_p, MaterialInstance *instance) 110 | { 111 | auto data = reinterpret_cast(data_p); 112 | 113 | UniformBuffer ubo; 114 | ubo.color_factor = instance->GetParameter(parameter_slot_base_color_factor, glm::vec4(1.0f, 1.0f, 1.0f, 1.0f)); 115 | ubo.specular_exponent = instance->GetParameter(parameter_slot_specular_exponent, 16.0f); 116 | 117 | memcpy(data->uniform_buffer->Map(), &ubo, sizeof(ubo)); 118 | data->uniform_buffer->UnMap(); 119 | } -------------------------------------------------------------------------------- /lavos/src/material/unlit_material.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "lavos/engine.h" 3 | #include "lavos/material/unlit_material.h" 4 | #include "lavos/material/material_instance.h" 5 | 6 | #include "lavos/shader_load.h" 7 | 8 | using namespace lavos; 9 | 10 | UnlitMaterial::UnlitMaterial(lavos::Engine *engine) : Material(engine) 11 | { 12 | CreateDescriptorSetLayouts(); 13 | 14 | vert_shader_module = CreateShaderModule(engine->GetVkDevice(), "material/unlit.vert"); 15 | frag_shader_module = CreateShaderModule(engine->GetVkDevice(), "material/unlit.frag"); 16 | 17 | texture_default_image = Texture::CreateColor(engine, vk::Format::eR8G8B8Unorm, glm::vec4(1.0f, 1.0f, 1.0f, 0.0f)); 18 | } 19 | 20 | UnlitMaterial::~UnlitMaterial() 21 | { 22 | auto &device = engine->GetVkDevice(); 23 | 24 | engine->DestroyTexture(texture_default_image); 25 | 26 | device.destroyShaderModule(vert_shader_module); 27 | device.destroyShaderModule(frag_shader_module); 28 | } 29 | 30 | void UnlitMaterial::CreateDescriptorSetLayouts() 31 | { 32 | std::vector bindings = { 33 | vk::DescriptorSetLayoutBinding() 34 | .setBinding(0) 35 | .setDescriptorType(vk::DescriptorType::eUniformBuffer) 36 | .setDescriptorCount(1) 37 | .setPImmutableSamplers(nullptr) 38 | .setStageFlags(vk::ShaderStageFlagBits::eFragment), 39 | 40 | vk::DescriptorSetLayoutBinding() 41 | .setBinding(1) 42 | .setDescriptorType(vk::DescriptorType::eCombinedImageSampler) 43 | .setDescriptorCount(1) 44 | .setPImmutableSamplers(nullptr) 45 | .setStageFlags(vk::ShaderStageFlagBits::eFragment) 46 | }; 47 | 48 | CreateDescriptorSetLayout(DescriptorSetLayoutIdDefault, bindings); 49 | } 50 | 51 | std::vector UnlitMaterial::GetShaderStageCreateInfos(RenderMode render_mode) const 52 | { 53 | return { 54 | vk::PipelineShaderStageCreateInfo(vk::PipelineShaderStageCreateFlags(), 55 | vk::ShaderStageFlagBits::eVertex, 56 | vert_shader_module, 57 | "main"), 58 | vk::PipelineShaderStageCreateInfo(vk::PipelineShaderStageCreateFlags(), 59 | vk::ShaderStageFlagBits::eFragment, 60 | frag_shader_module, 61 | "main") 62 | }; 63 | } 64 | 65 | void UnlitMaterial::WriteDescriptorSet(DescriptorSetId id, vk::DescriptorSet descriptor_set, MaterialInstance *instance) 66 | { 67 | auto instance_data = reinterpret_cast(instance->GetInstanceData(id)); 68 | 69 | auto ubo_info = vk::DescriptorBufferInfo() 70 | .setBuffer(instance_data->uniform_buffer->GetVkBuffer()) 71 | .setOffset(0) 72 | .setRange(sizeof(UniformBuffer)); 73 | 74 | auto ubo_write = vk::WriteDescriptorSet() 75 | .setDstSet(descriptor_set) 76 | .setDstBinding(0) 77 | .setDstArrayElement(0) 78 | .setDescriptorType(vk::DescriptorType::eUniformBuffer) 79 | .setDescriptorCount(1) 80 | .setPBufferInfo(&ubo_info); 81 | 82 | 83 | 84 | Texture *texture = instance->GetTexture(texture_slot_base_color); 85 | if(texture == nullptr) 86 | texture = &texture_default_image; 87 | 88 | auto image_info = vk::DescriptorImageInfo() 89 | .setImageLayout(vk::ImageLayout::eShaderReadOnlyOptimal) 90 | .setImageView(texture->image_view) 91 | .setSampler(texture->sampler); 92 | 93 | auto image_write = vk::WriteDescriptorSet() 94 | .setDstSet(descriptor_set) 95 | .setDstBinding(1) 96 | .setDstArrayElement(0) 97 | .setDescriptorType(vk::DescriptorType::eCombinedImageSampler) 98 | .setDescriptorCount(1) 99 | .setPImageInfo(&image_info); 100 | 101 | 102 | engine->GetVkDevice().updateDescriptorSets({image_write, ubo_write}, nullptr); 103 | } 104 | 105 | void *UnlitMaterial::CreateInstanceData(InstanceDataId id) 106 | { 107 | auto buffer = engine->CreateBuffer(sizeof(UniformBuffer), 108 | vk::BufferUsageFlagBits::eUniformBuffer, 109 | VMA_MEMORY_USAGE_CPU_ONLY); 110 | 111 | return new UBOInstanceData(buffer); 112 | } 113 | 114 | void UnlitMaterial::DestroyInstanceData(InstanceDataId id, void *data_p) 115 | { 116 | auto data = reinterpret_cast(data_p); 117 | delete data; 118 | } 119 | 120 | void UnlitMaterial::UpdateInstanceData(InstanceDataId id, void *data_p, MaterialInstance *instance) 121 | { 122 | auto data = reinterpret_cast(data_p); 123 | 124 | UniformBuffer ubo; 125 | 126 | ubo.color_factor = instance->GetParameter(parameter_slot_base_color_factor, glm::vec3(1.0f, 1.0f, 1.0f)); 127 | 128 | memcpy(data->uniform_buffer->Map(), &ubo, sizeof(ubo)); 129 | data->uniform_buffer->UnMap(); 130 | } -------------------------------------------------------------------------------- /lavos/src/material/material_instance.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "lavos/material/material.h" 3 | #include "lavos/material/material_instance.h" 4 | #include "lavos/engine.h" 5 | 6 | using namespace lavos; 7 | 8 | MaterialInstance::MaterialInstance(Material *material, const RenderConfig &render_config, vk::DescriptorPool descriptor_pool) 9 | : material(material), descriptor_pool(descriptor_pool) 10 | { 11 | for(auto render_mode : render_config.GetMaterialRenderModes()) 12 | { 13 | CreateDescriptorSet(material->GetDescriptorSetId(render_mode)); 14 | CreateInstanceData(material->GetInstanceDataId(render_mode)); 15 | } 16 | } 17 | 18 | MaterialInstance::~MaterialInstance() 19 | { 20 | auto engine = material->GetEngine(); 21 | 22 | for(auto it : instance_data) 23 | material->DestroyInstanceData(it.first, it.second); 24 | 25 | for(auto &entry : textures) 26 | engine->DestroyTexture(entry.second); 27 | 28 | for(auto it : descriptor_sets) 29 | engine->GetVkDevice().freeDescriptorSets(descriptor_pool, it.second); 30 | } 31 | 32 | void MaterialInstance::CreateDescriptorSet(Material::DescriptorSetId id) 33 | { 34 | if(descriptor_sets.find(id) != descriptor_sets.end()) 35 | return; 36 | 37 | auto engine = material->GetEngine(); 38 | auto layout = material->GetDescriptorSetLayout(id); 39 | 40 | if(!layout) 41 | return; 42 | 43 | vk::DescriptorSetLayout layouts[] = { layout->layout }; 44 | 45 | auto alloc_info = vk::DescriptorSetAllocateInfo() 46 | .setDescriptorPool(descriptor_pool) 47 | .setDescriptorSetCount(1) 48 | .setPSetLayouts(layouts); 49 | 50 | auto descriptor_set = *engine->GetVkDevice().allocateDescriptorSets(alloc_info).begin(); 51 | if(descriptor_set) 52 | descriptor_sets[id] = descriptor_set; 53 | } 54 | 55 | void MaterialInstance::CreateInstanceData(Material::InstanceDataId id) 56 | { 57 | if(instance_data.find(id) != instance_data.end()) 58 | return; 59 | 60 | instance_data[id] = material->CreateInstanceData(id); 61 | } 62 | 63 | void MaterialInstance::WriteDescriptorSet(Material::RenderMode render_mode) 64 | { 65 | auto descriptor_set = GetDescriptorSet(render_mode); 66 | if(descriptor_set) 67 | material->WriteDescriptorSet(render_mode, descriptor_set, this); 68 | } 69 | 70 | void MaterialInstance::WriteInstanceData(Material::RenderMode render_mode) 71 | { 72 | auto data = instance_data[render_mode]; 73 | material->UpdateInstanceData(render_mode, data, this); 74 | } 75 | 76 | void MaterialInstance::SetTexture(Material::TextureSlot slot, Texture texture) 77 | { 78 | if(texture == nullptr) 79 | { 80 | textures.erase(slot); 81 | return; 82 | } 83 | 84 | textures[slot] = texture; 85 | } 86 | 87 | Texture *MaterialInstance::GetTexture(Material::TextureSlot slot) 88 | { 89 | auto it = textures.find(slot); 90 | 91 | if(it != textures.end()) 92 | return &it->second; 93 | 94 | return nullptr; 95 | } 96 | 97 | void MaterialInstance::SetParameter(Material::ParameterSlot slot, MaterialInstance::Parameter parameter) 98 | { 99 | parameters.insert(std::make_pair(slot, parameter)); 100 | } 101 | 102 | MaterialInstance::Parameter *MaterialInstance::GetParameter(Material::ParameterSlot slot) 103 | { 104 | auto it = parameters.find(slot); 105 | 106 | if(it != parameters.end()) 107 | return &it->second; 108 | 109 | return nullptr; 110 | } 111 | 112 | float MaterialInstance::GetParameter(Material::ParameterSlot slot, float default_value) 113 | { 114 | auto it = parameters.find(slot); 115 | 116 | if(it != parameters.end()) 117 | return it->second.f; 118 | 119 | return default_value; 120 | } 121 | 122 | glm::vec2 MaterialInstance::GetParameter(Material::ParameterSlot slot, glm::vec2 default_value) 123 | { 124 | auto it = parameters.find(slot); 125 | 126 | if(it != parameters.end()) 127 | return it->second.v2; 128 | 129 | return default_value; 130 | } 131 | 132 | glm::vec3 MaterialInstance::GetParameter(Material::ParameterSlot slot, glm::vec3 default_value) 133 | { 134 | auto it = parameters.find(slot); 135 | 136 | if(it != parameters.end()) 137 | return it->second.v3; 138 | 139 | return default_value; 140 | } 141 | 142 | glm::vec4 MaterialInstance::GetParameter(Material::ParameterSlot slot, glm::vec4 default_value) 143 | { 144 | auto it = parameters.find(slot); 145 | 146 | if(it != parameters.end()) 147 | return it->second.v4; 148 | 149 | return default_value; 150 | } 151 | 152 | void MaterialInstance::WriteAllData() 153 | { 154 | for(auto it : instance_data) 155 | WriteInstanceData(it.first); 156 | 157 | for(auto it : descriptor_sets) 158 | WriteDescriptorSet(it.first); 159 | } 160 | -------------------------------------------------------------------------------- /demos/firstperson/firstperson.cpp: -------------------------------------------------------------------------------- 1 | 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #include 22 | 23 | 24 | 25 | lavos::shell::glfw::WindowApplication *app = nullptr; 26 | 27 | lavos::Renderer *renderer = nullptr; 28 | lavos::Material *material; 29 | 30 | lavos::AssetContainer *asset_container = nullptr; 31 | 32 | lavos::MaterialInstance *material_instance; 33 | 34 | lavos::Scene *scene; 35 | 36 | double last_cursor_x, last_cursor_y; 37 | lavos::FirstPersonController *fp_controller; 38 | 39 | 40 | 41 | void Init(std::string gltf_filename) 42 | { 43 | material = new lavos::GouraudMaterial(app->GetEngine()); 44 | 45 | auto render_config = lavos::RenderConfigBuilder().Build(); 46 | 47 | renderer = new lavos::Renderer(app->GetEngine(), render_config, app->GetSwapchain(), app->GetDepthRenderTarget()); 48 | renderer->AddMaterial(material); 49 | 50 | asset_container = lavos::AssetContainer::LoadFromGLTF(app->GetEngine(), render_config, material, gltf_filename); 51 | 52 | scene = asset_container->scenes[0]; 53 | scene->SetAmbientLightIntensity(glm::vec3(0.3f, 0.3f, 0.3f)); 54 | 55 | renderer->SetScene(scene); 56 | 57 | lavos::Camera *camera = scene->GetRootNode()->GetComponentInChildren(); 58 | lavos::Node *camera_node; 59 | if(camera == nullptr) 60 | { 61 | camera_node = new lavos::Node(); 62 | scene->GetRootNode()->AddChild(camera_node); 63 | camera_node->AddComponent(new lavos::TransformComp()); 64 | 65 | camera = new lavos::Camera(); 66 | camera->SetNearClip(0.01f); 67 | camera_node->AddComponent(camera); 68 | } 69 | else 70 | { 71 | camera_node = camera->GetNode(); 72 | } 73 | 74 | camera_node->GetTransformComp()->translation = glm::vec3(0.0f, 0.0f, 5.0f); 75 | camera_node->GetTransformComp()->SetLookAt(glm::vec3(0.0f, 0.0f, 0.0f)); 76 | 77 | fp_controller = new lavos::FirstPersonController(); 78 | camera_node->AddComponent(fp_controller); 79 | 80 | 81 | lavos::Node *light_node = new lavos::Node(); 82 | scene->GetRootNode()->AddChild(light_node); 83 | 84 | light_node->AddComponent(new lavos::TransformComp()); 85 | light_node->GetTransformComp()->SetLookAt(glm::vec3(-1.0f, -1.0f, -1.0f)); 86 | 87 | lavos::DirectionalLight *light = new lavos::DirectionalLight(); 88 | light_node->AddComponent(light); 89 | 90 | renderer->SetCamera(camera); 91 | 92 | material_instance = asset_container->material_instances.front(); 93 | 94 | 95 | GLFWwindow *window = app->GetWindow(); 96 | glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); 97 | glfwGetCursorPos(window, &last_cursor_x, &last_cursor_y); 98 | } 99 | 100 | 101 | 102 | 103 | void Update() 104 | { 105 | GLFWwindow *window = app->GetWindow(); 106 | 107 | if(glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) 108 | glfwSetWindowShouldClose(window, GLFW_TRUE); 109 | 110 | glm::vec2 cam_vel(0.0f); 111 | 112 | if(glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) 113 | cam_vel.y += 1.0f; 114 | 115 | if(glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) 116 | cam_vel.y -= 1.0f; 117 | 118 | if(glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) 119 | cam_vel.x -= 1.0f; 120 | 121 | if(glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) 122 | cam_vel.x += 1.0f; 123 | 124 | fp_controller->SetVelocity(cam_vel * 10.0f); 125 | 126 | double cursor_x, cursor_y; 127 | glfwGetCursorPos(window, &cursor_x, &cursor_y); 128 | fp_controller->Rotate(glm::vec2(cursor_x - last_cursor_x, cursor_y - last_cursor_y) * 0.003f); 129 | last_cursor_x = cursor_x; 130 | last_cursor_y = cursor_y; 131 | 132 | scene->Update(app->GetDeltaTime()); 133 | } 134 | 135 | 136 | void Cleanup() 137 | { 138 | delete asset_container; 139 | delete renderer; 140 | } 141 | 142 | int main(int argc, const char **argv) 143 | { 144 | std::string gltf_filename = "data/gltftest.gltf"; 145 | if(argc > 1) 146 | gltf_filename = argv[1]; 147 | 148 | app = new lavos::shell::glfw::WindowApplication(800, 600, "First Person", true); 149 | 150 | Init(gltf_filename); 151 | 152 | while(true) 153 | { 154 | app->BeginFrame(); 155 | app->Update(); 156 | 157 | Update(); 158 | 159 | if(glfwWindowShouldClose(app->GetWindow())) 160 | break; 161 | 162 | app->Render(renderer); 163 | app->EndFrame(); 164 | } 165 | 166 | Cleanup(); 167 | 168 | return EXIT_SUCCESS; 169 | } -------------------------------------------------------------------------------- /lavos/include/lavos/engine.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef LAVOS_ENGINE_H 3 | #define LAVOS_ENGINE_H 4 | 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | #include "lavos/buffer.h" 11 | #include "lavos/texture.h" 12 | 13 | namespace lavos 14 | { 15 | 16 | class Engine 17 | { 18 | public: 19 | struct CreateInfo 20 | { 21 | std::string app_info; 22 | bool enable_validation_layers = false; 23 | bool enable_renderdoc = false; 24 | std::set required_instance_extensions; 25 | std::set required_device_extensions; 26 | 27 | bool enable_anisotropy = true; 28 | 29 | CreateInfo() = default; 30 | }; 31 | 32 | struct QueueFamilyIndices 33 | { 34 | int graphics_family = -1; 35 | 36 | bool IsComplete() 37 | { 38 | return graphics_family >= 0; 39 | } 40 | }; 41 | 42 | private: 43 | const CreateInfo info; 44 | 45 | QueueFamilyIndices queue_family_indices; 46 | 47 | vk::Instance instance; 48 | vk::DebugUtilsMessengerEXT debug_utils_messenger; 49 | 50 | vk::PhysicalDevice physical_device; 51 | vk::Device device; 52 | 53 | VmaAllocator allocator; 54 | 55 | vk::Queue graphics_queue; 56 | 57 | 58 | vk::CommandPool transient_command_pool; 59 | vk::CommandPool render_command_pool; 60 | 61 | 62 | std::vector GetRequiredInstanceExtensions(); 63 | std::vector GetRequiredDeviceExtensions(); 64 | 65 | std::vector EnableValidationLayers(); 66 | 67 | void CreateInstance(); 68 | void SetupDebugCallback(); 69 | 70 | bool CheckDeviceExtensionSupport(vk::PhysicalDevice physical_device); 71 | bool IsPhysicalDeviceSuitable(vk::PhysicalDevice physical_device, vk::SurfaceKHR surface); 72 | void PickPhysicalDevice(vk::SurfaceKHR surface); 73 | QueueFamilyIndices FindQueueFamilies(vk::PhysicalDevice physical_device); 74 | void CreateLogicalDevice(); 75 | 76 | void CreateAllocator(); 77 | 78 | void CreateGlobalCommandPools(); 79 | 80 | public: 81 | Engine(const CreateInfo &info); 82 | ~Engine(); 83 | 84 | void InitializeForSurface(vk::SurfaceKHR surface); 85 | void InitializeWithPhysicalDevice(vk::PhysicalDevice physical_device); 86 | void InitializeWithPhysicalDeviceIndex(unsigned int index); 87 | void InitializeWithDevice(vk::PhysicalDevice physical_device, vk::Device device, vk::Queue graphics_queue); 88 | 89 | const vk::Instance &GetVkInstance() const { return instance; } 90 | const vk::PhysicalDevice &GetVkPhysicalDevice() const { return physical_device; } 91 | const vk::Device &GetVkDevice() const { return device; } 92 | const VmaAllocator &GetVmaAllocator() const { return allocator; }; 93 | 94 | const QueueFamilyIndices &GetQueueFamilyIndices() const { return queue_family_indices; } 95 | const vk::Queue &GetGraphicsQueue() const { return graphics_queue; } 96 | 97 | bool GetAnisotropyEnabled() { return info.enable_anisotropy; } 98 | 99 | uint32_t FindMemoryType(uint32_t type_filter, vk::MemoryPropertyFlags properties); 100 | int FindPresentQueueFamily(vk::SurfaceKHR surface); 101 | 102 | vk::Format FindSupportedFormat(const std::vector &candidates, vk::ImageTiling tiling, vk::FormatFeatureFlags features); 103 | vk::Format FindDepthFormat(); 104 | static bool HasStencilComponent(vk::Format format); 105 | 106 | vk::CommandPool GetRenderCommandPool() { return render_command_pool; } 107 | 108 | vk::CommandBuffer BeginSingleTimeCommandBuffer(); 109 | void EndSingleTimeCommandBuffer(vk::CommandBuffer command_buffer); 110 | 111 | Buffer *CreateBuffer(vk::DeviceSize size, vk::BufferUsageFlags usage, VmaMemoryUsage vma_usage, vk::SharingMode sharing_mode = vk::SharingMode::eExclusive); 112 | void DestroyBuffer(vk::Buffer buffer, VmaAllocation allocation); 113 | 114 | void *MapMemory(const VmaAllocation &allocation); 115 | void UnmapMemory(const VmaAllocation &allocation); 116 | 117 | void CopyBuffer(vk::Buffer src_buffer, vk::Buffer dst_buffer, vk::DeviceSize size); 118 | 119 | 120 | Image CreateImage(vk::ImageCreateInfo create_info, VmaMemoryUsage vma_usage); 121 | void DestroyImage(const Image &image); 122 | 123 | void DestroyTexture(const Texture &texture); 124 | 125 | Image Create2DImage(uint32_t width, uint32_t height, vk::Format format, vk::ImageTiling tiling, vk::ImageUsageFlags usage, VmaMemoryUsage vma_usage, vk::SharingMode sharing_mode = vk::SharingMode::eExclusive); 126 | 127 | void TransitionImageLayout(vk::Image image, vk::Format format, vk::ImageLayout old_layout, vk::ImageLayout new_layout, vk::ImageAspectFlags aspect_mask = vk::ImageAspectFlagBits::eColor); 128 | 129 | void CopyBufferTo2DImage(vk::Buffer src_buffer, vk::Image dst_image, uint32_t width, uint32_t height, vk::ImageAspectFlags aspect_mask = vk::ImageAspectFlagBits::eColor); 130 | }; 131 | 132 | } 133 | 134 | #endif //VULKAN_ENGINE_H 135 | -------------------------------------------------------------------------------- /demos/2d/2d.cpp: -------------------------------------------------------------------------------- 1 | 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #include 22 | 23 | 24 | 25 | lavos::shell::glfw::WindowApplication *app = nullptr; 26 | 27 | lavos::Renderer *renderer = nullptr; 28 | lavos::Material *material; 29 | 30 | lavos::AssetContainer *asset_container = nullptr; 31 | 32 | lavos::MaterialInstance *material_instance; 33 | 34 | lavos::Scene *scene; 35 | 36 | 37 | class CameraControllerComponent : public lavos::Component 38 | { 39 | private: 40 | glm::vec2 velocity; 41 | 42 | public: 43 | virtual void Update(float delta_time) override 44 | { 45 | lavos::TransformComp *transform = GetNode()->GetTransformComp(); 46 | 47 | glm::mat4 mat = transform->GetMatrix(); 48 | transform->translation += glm::vec3(velocity.x * delta_time, velocity.y * delta_time, 0.0f); 49 | } 50 | 51 | void SetVelocity(glm::vec2 velocity) { this->velocity = velocity; } 52 | }; 53 | 54 | CameraControllerComponent *camera_controller; 55 | 56 | 57 | void Init(std::string gltf_filename) 58 | { 59 | material = new lavos::GouraudMaterial(app->GetEngine()); 60 | 61 | auto render_config = lavos::RenderConfigBuilder().Build(); 62 | 63 | renderer = new lavos::Renderer(app->GetEngine(), render_config, app->GetSwapchain(), app->GetDepthRenderTarget()); 64 | renderer->AddMaterial(material); 65 | 66 | asset_container = lavos::AssetContainer::LoadFromGLTF(app->GetEngine(), render_config, material, gltf_filename); 67 | 68 | scene = asset_container->scenes[0]; 69 | scene->SetAmbientLightIntensity(glm::vec3(0.3f, 0.3f, 0.3f)); 70 | 71 | renderer->SetScene(scene); 72 | 73 | lavos::Camera *camera = scene->GetRootNode()->GetComponentInChildren(); 74 | lavos::Node *camera_node; 75 | if(camera == nullptr) 76 | { 77 | camera_node = new lavos::Node(); 78 | scene->GetRootNode()->AddChild(camera_node); 79 | camera_node->AddComponent(new lavos::TransformComp()); 80 | 81 | camera = new lavos::Camera(); 82 | camera->SetNearClip(0.01f); 83 | camera_node->AddComponent(camera); 84 | } 85 | else 86 | { 87 | camera_node = camera->GetNode(); 88 | } 89 | 90 | camera->SetType(lavos::Camera::Type::ORTHOGRAPHIC); 91 | camera->SetOrthographicParams(-2.0, 2.0, -2.0, 2.0); 92 | 93 | camera_node->GetTransformComp()->translation = glm::vec3(0.0f, 0.0f, 5.0f); 94 | camera_node->GetTransformComp()->SetLookAt(glm::vec3(0.0f, 0.0f, 0.0f)); 95 | 96 | camera_controller = new CameraControllerComponent(); 97 | camera_node->AddComponent(camera_controller); 98 | 99 | 100 | lavos::Node *light_node = new lavos::Node(); 101 | scene->GetRootNode()->AddChild(light_node); 102 | 103 | light_node->AddComponent(new lavos::TransformComp()); 104 | light_node->GetTransformComp()->SetLookAt(glm::vec3(-1.0f, -1.0f, -1.0f)); 105 | 106 | lavos::DirectionalLight *light = new lavos::DirectionalLight(); 107 | light_node->AddComponent(light); 108 | 109 | renderer->SetCamera(camera); 110 | 111 | material_instance = asset_container->material_instances.front(); 112 | } 113 | 114 | 115 | 116 | 117 | void Update() 118 | { 119 | GLFWwindow *window = app->GetWindow(); 120 | 121 | if(glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) 122 | glfwSetWindowShouldClose(window, GLFW_TRUE); 123 | 124 | glm::vec2 cam_vel(0.0f); 125 | 126 | if(glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) 127 | cam_vel.y += 1.0f; 128 | 129 | if(glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) 130 | cam_vel.y -= 1.0f; 131 | 132 | if(glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) 133 | cam_vel.x -= 1.0f; 134 | 135 | if(glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) 136 | cam_vel.x += 1.0f; 137 | 138 | camera_controller->SetVelocity(cam_vel * 10.0f); 139 | 140 | scene->Update(app->GetDeltaTime()); 141 | } 142 | 143 | 144 | void Cleanup() 145 | { 146 | delete asset_container; 147 | delete renderer; 148 | } 149 | 150 | int main(int argc, const char **argv) 151 | { 152 | std::string gltf_filename = "data/gltftest.gltf"; 153 | if(argc > 1) 154 | gltf_filename = argv[1]; 155 | 156 | app = new lavos::shell::glfw::WindowApplication(800, 600, "First Person", true); 157 | 158 | Init(gltf_filename); 159 | 160 | while(true) 161 | { 162 | app->BeginFrame(); 163 | app->Update(); 164 | 165 | Update(); 166 | 167 | if(glfwWindowShouldClose(app->GetWindow())) 168 | break; 169 | 170 | app->Render(renderer); 171 | app->EndFrame(); 172 | } 173 | 174 | Cleanup(); 175 | 176 | return EXIT_SUCCESS; 177 | } -------------------------------------------------------------------------------- /lavos/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | option(LAVOS_IMPLEMENT_TINYGLTF "Compile implementation of tinygltf inside lavos." ON) 3 | option(LAVOS_IMPLEMENT_STB_IMAGE "Compile implementation of stb_image inside lavos." ON) 4 | option(LAVOS_IMPLEMENT_VMA "Compile implementation of Vulkan Memory Allocator inside lavos." ON) 5 | 6 | option(LAVOS_ENABLE_RENDERDOC "Enable RenderDoc integration." OFF) 7 | option(LAVOS_ENABLE_VK_NAMES "Enable naming vulkan objects for debugging." OFF) 8 | 9 | list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") 10 | 11 | set(SOURCE_FILES 12 | src/thirdparty_impl.cpp 13 | src/engine.cpp 14 | include/lavos/engine.h 15 | include/lavos/vertex.h 16 | src/mesh.cpp 17 | include/lavos/mesh.h 18 | src/material/material.cpp 19 | include/lavos/material/material.h 20 | src/material/unlit_material.cpp 21 | include/lavos/material/unlit_material.h 22 | src/material/phong_material.cpp 23 | include/lavos/material/phong_material.h 24 | src/material/gouraud_material.cpp 25 | include/lavos/material/gouraud_material.h 26 | src/material/material_instance.cpp 27 | include/lavos/material/material_instance.h 28 | include/lavos/buffer.h 29 | src/image.cpp 30 | include/lavos/image.h 31 | src/texture.cpp 32 | include/lavos/texture.h 33 | include/lavos/glm_config.h 34 | src/asset_container.cpp 35 | include/lavos/asset_container.h 36 | src/renderer.cpp 37 | include/lavos/renderer.h 38 | src/shader_load.cpp 39 | include/lavos/shader_load.h 40 | src/scene.cpp 41 | include/lavos/scene.h 42 | src/node.cpp 43 | include/lavos/node.h 44 | include/lavos/component/component.h 45 | src/component/mesh_component.cpp 46 | include/lavos/component/mesh_component.h 47 | include/lavos/component/transform_component.h 48 | src/component/transform_component.cpp 49 | include/lavos/component/camera.h 50 | src/glm_stream.h 51 | src/component/directional_light.cpp 52 | include/lavos/component/directional_light.h 53 | src/component/fp_controller.cpp 54 | include/lavos/component/fp_controller.h 55 | include/lavos/render_target.h 56 | src/render_target.cpp 57 | include/lavos/swapchain.h 58 | src/swapchain.cpp 59 | include/lavos/material/point_cloud_material.h 60 | src/material/point_cloud_material.cpp 61 | include/lavos/point_cloud.h 62 | include/lavos/component/point_cloud_component.h 63 | include/lavos/renderable.h 64 | include/lavos/component/spot_light.h 65 | src/component/spot_light.cpp 66 | include/lavos/spot_light_shadow.h 67 | src/spot_light_shadow.cpp 68 | src/buffer.cpp 69 | include/lavos/render_config.h 70 | src/render_config.cpp 71 | include/lavos/material_pipeline_manager.h 72 | src/material_pipeline_manager.cpp 73 | include/lavos/sub_renderer.h 74 | src/sub_renderer.cpp 75 | include/lavos/spot_light_shadow_renderer.h 76 | src/spot_light_shadow_renderer.cpp 77 | include/lavos/log.h 78 | src/log.cpp 79 | include/lavos/vk_util.h 80 | include/lavos/light_collection.h 81 | src/light_collection.cpp) 82 | 83 | set(GLSL_FILES 84 | material/unlit.vf.shader 85 | material/phong.vf.shader 86 | material/gouraud.vf.shader 87 | material/point_cloud.vf.shader 88 | material/shadow.vf.shader) 89 | 90 | 91 | 92 | 93 | if(LAVOS_IMPLEMENT_TINYGLTF) 94 | add_definitions(-DLAVOS_IMPLEMENT_TINYGLTF) 95 | endif() 96 | 97 | if(LAVOS_IMPLEMENT_STB_IMAGE) 98 | add_definitions(-DLAVOS_IMPLEMENT_STB_IMAGE) 99 | endif() 100 | 101 | if(LAVOS_IMPLEMENT_VMA) 102 | add_definitions(-DLAVOS_IMPLEMENT_VMA) 103 | endif() 104 | 105 | if(LAVOS_ENABLE_RENDERDOC) 106 | add_definitions(-DLAVOS_ENABLE_RENDERDOC) 107 | endif() 108 | 109 | if(LAVOS_ENABLE_VK_NAMES) 110 | add_definitions(-DLAVOS_ENABLE_VK_NAMES) 111 | endif() 112 | 113 | include(ShaderResources) 114 | 115 | add_spirv_shaders(VAR SPIRV_FILES 116 | BASE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/glsl" 117 | TARGET_DIR "${CMAKE_CURRENT_BINARY_DIR}/shader" 118 | ${GLSL_FILES}) 119 | 120 | set(RESOURCES_SRC_DIR "${CMAKE_CURRENT_BINARY_DIR}/spirv_resources") 121 | set(RESOURCES_HEADER "${RESOURCES_SRC_DIR}/spirv_resources.h") 122 | set(RESOURCES_SRC "${RESOURCES_SRC_DIR}/spirv_resources.cpp") 123 | set(RESOURCES_RELATIVE_PATH "${CMAKE_CURRENT_BINARY_DIR}/shader") 124 | file(MAKE_DIRECTORY ${RESOURCES_SRC_DIR}) 125 | include_directories(${RESOURCES_SRC_DIR}) 126 | generate_resources(SETUP GENERATE_HEADER 127 | BINARY 128 | RELATIVE_PATH ${RESOURCES_RELATIVE_PATH} 129 | HEADER_FILE ${RESOURCES_HEADER} 130 | HEADER_FILE_RELATIVE_PATH ${RESOURCES_SRC_DIR} 131 | SOURCE_FILE ${RESOURCES_SRC} 132 | FUNCTION_PREFIX "spirv_resources" 133 | INCLUDE_GUARD "SPIRV_RESOURCES" 134 | FILES ${SPIRV_FILES}) 135 | 136 | 137 | add_library(lavos SHARED ${SOURCE_FILES} ${RESOURCES_HEADERS} ${RESOURCES_SRC}) 138 | target_link_libraries(lavos ${Vulkan_LIBRARIES}) 139 | target_include_directories(lavos PUBLIC 140 | "${CMAKE_CURRENT_SOURCE_DIR}/include" 141 | "${CMAKE_CURRENT_SOURCE_DIR}/../thirdparty/vma/src") 142 | 143 | 144 | 145 | -------------------------------------------------------------------------------- /lavos/src/image.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "lavos/image.h" 5 | #include "lavos/vk_util.h" 6 | 7 | #include "stb_image.h" 8 | 9 | using namespace lavos; 10 | using namespace lavos::vk_util; 11 | 12 | unsigned char *ReformatImageData(unsigned int src_components, unsigned int dst_components, 13 | size_t pixel_count, unsigned char *pixels, 14 | std::array default_values = { 0, 0, 0, 255 }) 15 | { 16 | unsigned char *dst_pixels = new unsigned char[dst_components * pixel_count]; 17 | 18 | for(size_t i=0; iFindSupportedFormat({format, vk::Format::eR8G8B8A8Unorm}, 37 | vk::ImageTiling::eOptimal, 38 | vk::FormatFeatureFlagBits::eSampledImage); 39 | } 40 | 41 | vk::DeviceSize image_size = static_cast(width * height * GetComponentsCount(actual_format) * GetComponentSize(actual_format)); 42 | 43 | unsigned char *image_pixels = pixels; 44 | if(actual_format != format) 45 | { 46 | image_pixels = ReformatImageData(GetComponentsCount(format), 47 | GetComponentsCount(actual_format), width * height, pixels); 48 | } 49 | 50 | 51 | auto staging_buffer = engine->CreateBuffer(image_size, vk::BufferUsageFlagBits::eTransferSrc, VMA_MEMORY_USAGE_CPU_ONLY); 52 | 53 | memcpy(staging_buffer->Map(), image_pixels, image_size); 54 | staging_buffer->UnMap(); 55 | 56 | if(image_pixels != pixels) 57 | delete [] image_pixels; 58 | 59 | Image image = engine->Create2DImage(width, height, actual_format, vk::ImageTiling::eOptimal, 60 | vk::ImageUsageFlagBits::eTransferDst | vk::ImageUsageFlagBits::eSampled, 61 | VMA_MEMORY_USAGE_GPU_ONLY); 62 | 63 | 64 | vk::ImageAspectFlags aspect_mask = GetFormatIsDepth(format) ? vk::ImageAspectFlagBits::eDepth : vk::ImageAspectFlagBits::eColor; 65 | engine->TransitionImageLayout(image.image, actual_format, vk::ImageLayout::eUndefined, vk::ImageLayout::eTransferDstOptimal, aspect_mask); 66 | engine->CopyBufferTo2DImage(staging_buffer->GetVkBuffer(), image.image, static_cast(width), static_cast(height), aspect_mask); 67 | engine->TransitionImageLayout(image.image, actual_format, vk::ImageLayout::eTransferDstOptimal, vk::ImageLayout::eShaderReadOnlyOptimal, aspect_mask); 68 | 69 | delete staging_buffer; 70 | 71 | return image; 72 | } 73 | 74 | Image Image::LoadFromFile(Engine *engine, std::string file) 75 | { 76 | int width, height, channels; 77 | stbi_uc *pixels = stbi_load(file.c_str(), &width, &height, &channels, STBI_rgb_alpha); 78 | 79 | if (!pixels) 80 | throw std::runtime_error(std::string("failed to load image \"" + file + "\": ") + stbi_failure_reason()); 81 | 82 | Image r = LoadFromPixelData(engine, vk::Format::eR8G8B8A8Unorm, 83 | static_cast(width), static_cast(height), pixels); 84 | 85 | stbi_image_free(pixels); 86 | 87 | return r; 88 | } 89 | 90 | Image Image::LoadFromMemory(Engine *engine, unsigned char *data, size_t size) 91 | { 92 | int width, height, channels; 93 | stbi_uc *pixels = stbi_load_from_memory(data, static_cast(size), &width, &height, &channels, STBI_rgb_alpha); 94 | 95 | if (!pixels) 96 | throw std::runtime_error(std::string("failed to load image from memory: ") + stbi_failure_reason()); 97 | 98 | Image r = LoadFromPixelData(engine, vk::Format::eR8G8B8A8Unorm, 99 | static_cast(width), static_cast(height), pixels); 100 | 101 | stbi_image_free(pixels); 102 | 103 | return r; 104 | } 105 | 106 | Image Image::CreateColor(Engine *engine, vk::Format format, glm::vec4 color) 107 | { 108 | size_t components = GetComponentsCount(format); 109 | size_t component_size = GetComponentSize(format); 110 | 111 | // TODO: this all won't work if the format isn't uint 112 | uint8_t *pixels = new uint8_t[components * component_size]; 113 | if(component_size == 1) 114 | { 115 | for(size_t i=0; i(color[i] * 255.0f); 117 | } 118 | else if(component_size == 2) 119 | { 120 | for(size_t i=0; i(color[i] * 255.0f); 122 | } 123 | else 124 | { 125 | // TODO: add support for more formats 126 | throw std::runtime_error("unsupported format for creating single color image."); 127 | } 128 | 129 | Image image = LoadFromPixelData(engine, format, 1, 1, pixels); 130 | 131 | delete[] pixels; 132 | 133 | return image; 134 | } 135 | -------------------------------------------------------------------------------- /lavos/cmake/ResourceGenerator.cmake: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.2) 2 | 3 | include(CMakeParseArguments) 4 | 5 | set(RESOURCE_GENERATOR_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}) 6 | 7 | function(generate_resources) 8 | set(options SETUP GENERATE_HEADER GENERATE_SOURCE BINARY) 9 | set(one_value_args RELATIVE_PATH HEADER_FILE HEADER_FILE_RELATIVE_PATH SOURCE_FILE FUNCTION_PREFIX INCLUDE_GUARD TYPE) 10 | set(multi_value_args FILES) 11 | cmake_parse_arguments(RESOURCE_GENERATOR "${options}" "${one_value_args}" "${multi_value_args}" ${ARGN}) 12 | 13 | if(NOT RESOURCE_GENERATOR_FUNCTION_PREFIX) 14 | set(RESOURCE_GENERATOR_FUNCTION_PREFIX "resources") 15 | endif() 16 | 17 | if(NOT RESOURCE_GENERATOR_TYPE) 18 | if(RESOURCE_GENERATOR_BINARY) 19 | set(RESOURCE_GENERATOR_TYPE "unsigned char") 20 | else() 21 | set(RESOURCE_GENERATOR_TYPE "char") 22 | endif() 23 | endif() 24 | 25 | 26 | if(RESOURCE_GENERATOR_GENERATE_HEADER) 27 | message("Generating resource header ${RESOURCE_GENERATOR_HEADER_FILE}") 28 | 29 | if(NOT RESOURCE_GENERATOR_INCLUDE_GUARD) 30 | string(TOUPPER ${RESOURCE_GENERATOR_FUNCTION_PREFIX} RESOURCE_GENERATOR_INCLUDE_GUARD) 31 | endif() 32 | configure_file("${RESOURCE_GENERATOR_ROOT_DIR}/ResourceGenerator_header.h.in" ${RESOURCE_GENERATOR_HEADER_FILE}) 33 | endif() 34 | 35 | 36 | 37 | 38 | if(RESOURCE_GENERATOR_GENERATE_SOURCE) 39 | message("Generating resource source ${RESOURCE_GENERATOR_SOURCE_FILE}") 40 | 41 | set(RESOURCE_GENERATOR_RESOURCES_SOURCE "") 42 | set(RESOURCE_GENERATOR_GET_FUNCTION_SOURCE "") 43 | set(RESOURCE_GENERATOR_RESOURCES_ALL " ") 44 | set(RESOURCE_GENERATOR_RESOURCES_ALL_NAMES " ") 45 | 46 | set(resource_index 0) 47 | 48 | foreach(file ${RESOURCE_GENERATOR_FILES}) 49 | file(RELATIVE_PATH file_rel ${RESOURCE_GENERATOR_RELATIVE_PATH} ${file}) 50 | 51 | if(RESOURCE_GENERATOR_BINARY) 52 | file(READ ${file} file_content_hex HEX) 53 | string(LENGTH "${file_content_hex}" file_content_length) 54 | set(char_index 0) 55 | set(file_content "") 56 | while(char_index LESS file_content_length) 57 | string(SUBSTRING "${file_content_hex}" ${char_index} 2 byte) 58 | math(EXPR char_index "${char_index}+2") 59 | set(file_content "${file_content}0x${byte}, ") 60 | endwhile() 61 | set(file_content "{ ${file_content}}") 62 | math(EXPR file_content_length "${file_content_length}/2") 63 | else() 64 | file(READ ${file} file_content) 65 | string(LENGTH "${file_content}" file_content_length) 66 | string(REPLACE "\"" "\\\"" file_content "${file_content}") 67 | string(REPLACE "\n" "\\n\"\n\t\"" file_content "${file_content}") 68 | set(file_content "\"${file_content}\"") 69 | endif() 70 | 71 | set(variable_name "resource_data_${resource_index}") 72 | 73 | set(RESOURCE_GENERATOR_RESOURCES_SOURCE "${RESOURCE_GENERATOR_RESOURCES_SOURCE}static const ${RESOURCE_GENERATOR_TYPE} ${variable_name}[] =\n\t${file_content};\n\n") 74 | set(RESOURCE_GENERATOR_GET_FUNCTION_SOURCE "${RESOURCE_GENERATOR_GET_FUNCTION_SOURCE}\tif(strcmp(filename, \"${file_rel}\") == 0)\n\t{\n\t\tif(size != 0)\n\t\t\t*size = ${file_content_length};\n\t\treturn ${variable_name};\n\t}\n") 75 | set(RESOURCE_GENERATOR_RESOURCES_ALL "${RESOURCE_GENERATOR_RESOURCES_ALL}${variable_name}, ") 76 | set(RESOURCE_GENERATOR_RESOURCES_ALL_NAMES "${RESOURCE_GENERATOR_RESOURCES_ALL_NAMES}\"${file_rel}\", ") 77 | 78 | math(EXPR resource_index "${resource_index}+1") 79 | endforeach() 80 | 81 | set(RESOURCE_GENERATOR_RESOURCES_COUNT ${resource_index}) 82 | 83 | file(RELATIVE_PATH RESOURCE_GENERATOR_HEADER_FILE_RELATIVE "${RESOURCE_GENERATOR_HEADER_FILE_RELATIVE_PATH}" "${RESOURCE_GENERATOR_HEADER_FILE}") 84 | 85 | configure_file("${RESOURCE_GENERATOR_ROOT_DIR}/ResourceGenerator_source.cpp.in" ${RESOURCE_GENERATOR_SOURCE_FILE}) 86 | endif() 87 | 88 | 89 | 90 | if(RESOURCE_GENERATOR_SETUP) 91 | set(GENERATE_RESOURCES_ARGS "") 92 | if(RESOURCE_GENERATOR_BINARY) 93 | set(GENERATE_RESOURCES_ARGS "${GENERATE_RESOURCES_ARGS} BINARY") 94 | endif() 95 | set(GENERATE_RESOURCES_ARGS "${GENERATE_RESOURCES_ARGS} 96 | RELATIVE_PATH \"${RESOURCE_GENERATOR_RELATIVE_PATH}\" 97 | HEADER_FILE \"${RESOURCE_GENERATOR_HEADER_FILE}\" 98 | HEADER_FILE_RELATIVE_PATH \"${RESOURCE_GENERATOR_HEADER_FILE_RELATIVE_PATH}\" 99 | SOURCE_FILE \"${RESOURCE_GENERATOR_SOURCE_FILE}\" 100 | FUNCTION_PREFIX \"${RESOURCE_GENERATOR_FUNCTION_PREFIX}\" 101 | FUNCTION_PREFIX \"${RESOURCE_GENERATOR_FUNCTION_PREFIX}\" 102 | TYPE \"${RESOURCE_GENERATOR_TYPE}\" 103 | FILES ${RESOURCE_GENERATOR_FILES}") 104 | 105 | set(RESOURCE_GENERATOR_INCLUDE "${CMAKE_CURRENT_SOURCE_DIR}/cmake/ResourceGenerator.cmake") 106 | configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake/generate_resources_src.cmake.in" 107 | "${CMAKE_CURRENT_BINARY_DIR}/generate_resources_src.cmake") 108 | 109 | add_custom_command(OUTPUT "${RESOURCE_GENERATOR_SOURCE_FILE}" 110 | COMMAND "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/generate_resources_src.cmake" 111 | DEPENDS ${RESOURCE_GENERATOR_FILES}) 112 | endif() 113 | 114 | endfunction(generate_resources) -------------------------------------------------------------------------------- /shell/qt/src/lavos_window.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "lavos_window.h" 9 | 10 | #include 11 | 12 | 13 | using namespace lavos::shell::qt; 14 | 15 | 16 | LavosWindow::LavosWindow(lavos::Engine *engine, Renderer *renderer, QWindow *parent) 17 | : QWindow(parent), engine(engine), renderer(renderer) 18 | { 19 | vulkan_initialized = false; 20 | setSurfaceType(VulkanSurface); 21 | } 22 | 23 | LavosWindow::~LavosWindow() 24 | { 25 | CleanupVulkan(); 26 | } 27 | 28 | void LavosWindow::InitializeVulkan() 29 | { 30 | surface = QVulkanInstance::surfaceForWindow(this); 31 | present_queue_family_index = static_cast(engine->FindPresentQueueFamily(surface)); 32 | present_queue = engine->GetVkDevice().getQueue(present_queue_family_index, 0); 33 | vk::Extent2D extent(static_cast(width()), static_cast(height())); 34 | swapchain = new lavos::Swapchain(engine, surface, present_queue_family_index, extent); 35 | depth_render_target = new lavos::ManagedDepthRenderTarget(engine, swapchain); 36 | 37 | image_available_semaphore = engine->GetVkDevice().createSemaphore(vk::SemaphoreCreateInfo()); 38 | render_finished_semaphore = engine->GetVkDevice().createSemaphore(vk::SemaphoreCreateInfo()); 39 | 40 | vulkan_initialized = true; 41 | } 42 | 43 | void LavosWindow::CleanupVulkan() 44 | { 45 | auto device = engine->GetVkDevice(); 46 | 47 | delete swapchain; 48 | swapchain = nullptr; 49 | delete depth_render_target; 50 | depth_render_target = nullptr; 51 | 52 | if(image_available_semaphore) 53 | { 54 | device.destroySemaphore(image_available_semaphore); 55 | image_available_semaphore = nullptr; 56 | } 57 | 58 | if(render_finished_semaphore) 59 | { 60 | device.destroySemaphore(render_finished_semaphore); 61 | render_finished_semaphore = nullptr; 62 | } 63 | 64 | vulkan_initialized = false; 65 | } 66 | 67 | void LavosWindow::RecreateSwapchain() 68 | { 69 | swapchain->Recreate(); 70 | requestUpdate(); 71 | } 72 | 73 | void LavosWindow::Render(lavos::Renderer *renderer) 74 | { 75 | if (!isExposed()) 76 | { 77 | return; 78 | } 79 | 80 | auto image_index_result = engine->GetVkDevice().acquireNextImageKHR(swapchain->GetSwapchain(), 81 | std::numeric_limits::max(), 82 | image_available_semaphore, 83 | vk::Fence() /*nullptr*/); 84 | 85 | if(image_index_result.result == vk::Result::eErrorOutOfDateKHR) 86 | { 87 | RecreateSwapchain(); 88 | return; 89 | } 90 | else if(image_index_result.result != vk::Result::eSuccess && image_index_result.result != vk::Result::eSuboptimalKHR) 91 | { 92 | throw std::runtime_error("failed to acquire swap chain image!"); 93 | } 94 | 95 | uint32_t image_index = image_index_result.value; 96 | 97 | renderer->DrawFrame(image_index, 98 | { image_available_semaphore }, 99 | { vk::PipelineStageFlagBits::eColorAttachmentOutput }, 100 | { render_finished_semaphore }); 101 | 102 | vk::Semaphore signal_semaphores[] = { render_finished_semaphore }; 103 | 104 | vk::SwapchainKHR vk_swapchain = swapchain->GetSwapchain(); 105 | vk::Result present_result; 106 | try 107 | { 108 | present_result = present_queue.presentKHR(vk::PresentInfoKHR() 109 | .setWaitSemaphoreCount(1) 110 | .setPWaitSemaphores(signal_semaphores) 111 | .setSwapchainCount(1) 112 | .setPSwapchains(&vk_swapchain) 113 | .setPImageIndices(&image_index)); 114 | } 115 | catch(vk::OutOfDateKHRError) 116 | { 117 | RecreateSwapchain(); 118 | present_result = vk::Result::eSuccess; 119 | } 120 | 121 | if(present_result == vk::Result::eSuboptimalKHR) 122 | { 123 | RecreateSwapchain(); 124 | } 125 | else if(present_result != vk::Result::eSuccess) 126 | { 127 | throw std::runtime_error("failed to present swap chain image!"); 128 | } 129 | 130 | vulkanInstance()->presentQueued(this); 131 | present_queue.waitIdle(); 132 | } 133 | 134 | bool LavosWindow::event(QEvent *event) 135 | { 136 | switch(event->type()) 137 | { 138 | case QEvent::PlatformSurface: 139 | { 140 | QPlatformSurfaceEvent *surface_event = static_cast(event); 141 | if(surface_event->surfaceEventType() == QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed) 142 | { 143 | renderer->ReleaseSwapchainResources(); 144 | CleanupVulkan(); 145 | } 146 | break; 147 | } 148 | 149 | case QEvent::UpdateRequest: 150 | renderer->Render(this); 151 | break; 152 | 153 | default: 154 | break; 155 | } 156 | 157 | return QWindow::event(event); 158 | } 159 | 160 | void LavosWindow::exposeEvent(QExposeEvent *ev) 161 | { 162 | if(isExposed()) 163 | { 164 | if(!vulkan_initialized) 165 | { 166 | InitializeVulkan(); 167 | renderer->InitializeSwapchainResources(this); 168 | } 169 | requestUpdate(); 170 | } 171 | 172 | QWindow::exposeEvent(ev); 173 | } 174 | 175 | void LavosWindow::resizeEvent(QResizeEvent *) 176 | { 177 | } 178 | -------------------------------------------------------------------------------- /android/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # Attempt to set APP_HOME 46 | # Resolve links: $0 may be a link 47 | PRG="$0" 48 | # Need this for relative symlinks. 49 | while [ -h "$PRG" ] ; do 50 | ls=`ls -ld "$PRG"` 51 | link=`expr "$ls" : '.*-> \(.*\)$'` 52 | if expr "$link" : '/.*' > /dev/null; then 53 | PRG="$link" 54 | else 55 | PRG=`dirname "$PRG"`"/$link" 56 | fi 57 | done 58 | SAVED="`pwd`" 59 | cd "`dirname \"$PRG\"`/" >/dev/null 60 | APP_HOME="`pwd -P`" 61 | cd "$SAVED" >/dev/null 62 | 63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 64 | 65 | # Determine the Java command to use to start the JVM. 66 | if [ -n "$JAVA_HOME" ] ; then 67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 68 | # IBM's JDK on AIX uses strange locations for the executables 69 | JAVACMD="$JAVA_HOME/jre/sh/java" 70 | else 71 | JAVACMD="$JAVA_HOME/bin/java" 72 | fi 73 | if [ ! -x "$JAVACMD" ] ; then 74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 75 | 76 | Please set the JAVA_HOME variable in your environment to match the 77 | location of your Java installation." 78 | fi 79 | else 80 | JAVACMD="java" 81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 82 | 83 | Please set the JAVA_HOME variable in your environment to match the 84 | location of your Java installation." 85 | fi 86 | 87 | # Increase the maximum file descriptors if we can. 88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 89 | MAX_FD_LIMIT=`ulimit -H -n` 90 | if [ $? -eq 0 ] ; then 91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 92 | MAX_FD="$MAX_FD_LIMIT" 93 | fi 94 | ulimit -n $MAX_FD 95 | if [ $? -ne 0 ] ; then 96 | warn "Could not set maximum file descriptor limit: $MAX_FD" 97 | fi 98 | else 99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 100 | fi 101 | fi 102 | 103 | # For Darwin, add options to specify how the application appears in the dock 104 | if $darwin; then 105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 106 | fi 107 | 108 | # For Cygwin, switch paths to Windows format before running java 109 | if $cygwin ; then 110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 112 | JAVACMD=`cygpath --unix "$JAVACMD"` 113 | 114 | # We build the pattern for arguments to be converted via cygpath 115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 116 | SEP="" 117 | for dir in $ROOTDIRSRAW ; do 118 | ROOTDIRS="$ROOTDIRS$SEP$dir" 119 | SEP="|" 120 | done 121 | OURCYGPATTERN="(^($ROOTDIRS))" 122 | # Add a user-defined pattern to the cygpath arguments 123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 125 | fi 126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 127 | i=0 128 | for arg in "$@" ; do 129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 131 | 132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 134 | else 135 | eval `echo args$i`="\"$arg\"" 136 | fi 137 | i=$((i+1)) 138 | done 139 | case $i in 140 | (0) set -- ;; 141 | (1) set -- "$args0" ;; 142 | (2) set -- "$args0" "$args1" ;; 143 | (3) set -- "$args0" "$args1" "$args2" ;; 144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 150 | esac 151 | fi 152 | 153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 154 | function splitJvmOpts() { 155 | JVM_OPTS=("$@") 156 | } 157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 159 | 160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 161 | -------------------------------------------------------------------------------- /lavos/include/lavos/renderer.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef LAVOS_RENDERER_H 3 | #define LAVOS_RENDERER_H 4 | 5 | #include 6 | #include 7 | 8 | #include "lavos/component/camera.h" 9 | #include "engine.h" 10 | #include "material/material.h" 11 | #include "mesh.h" 12 | #include "scene.h" 13 | #include "render_target.h" 14 | #include "render_config.h" 15 | #include "material_pipeline_manager.h" 16 | 17 | namespace lavos 18 | { 19 | 20 | class SpotLight; 21 | class SpotLightShadow; 22 | class SubRenderer; 23 | class LightCollection; 24 | 25 | struct MatrixUniformBuffer 26 | { 27 | glm::mat4 modelview; 28 | glm::mat4 projection; 29 | }; 30 | 31 | static_assert(sizeof(MatrixUniformBuffer) == 128, "MatrixUniformBuffer memory layout"); 32 | 33 | 34 | struct LightingUniformBufferFixed 35 | { 36 | glm::vec3 ambient_intensity; 37 | std::uint32_t directional_light_enabled; 38 | glm::vec3 directional_light_dir; 39 | std::uint8_t unused_2[4]; 40 | glm::vec3 directional_light_intensity; 41 | std::uint32_t spot_lights_count; 42 | }; 43 | 44 | struct LightingUniformBufferSpotLight 45 | { 46 | glm::vec3 position; 47 | float angle_cos; 48 | glm::vec3 direction; 49 | float unused; 50 | glm::mat4 shadow_mvp_matrix; 51 | }; 52 | 53 | static_assert(sizeof(LightingUniformBufferFixed) == 48, "LightingUniformBufferFixed memory layout"); 54 | static_assert(sizeof(LightingUniformBufferSpotLight) == 96, "LightingUniformBufferSpotLight memory layout"); 55 | 56 | 57 | struct CameraUniformBuffer 58 | { 59 | glm::vec3 position; 60 | }; 61 | 62 | static_assert(sizeof(CameraUniformBuffer) == 12, "CameraUniformBuffer memory layout"); 63 | 64 | 65 | struct TransformPushConstant 66 | { 67 | glm::mat4 transform; 68 | }; 69 | 70 | static_assert(sizeof(TransformPushConstant) == 64, "TransformPushConstant memory layout"); 71 | 72 | 73 | 74 | class Renderer: public ColorRenderTarget::ChangedCallback 75 | { 76 | friend class MaterialPipelineManager; 77 | 78 | private: 79 | Engine * const engine; 80 | 81 | const RenderConfig config; 82 | 83 | Scene *scene = nullptr; 84 | Camera *camera = nullptr; 85 | 86 | bool auto_set_camera_aspect = true; 87 | 88 | vk::CommandBuffer render_command_buffer; 89 | 90 | ColorRenderTarget *color_render_target; 91 | DepthRenderTarget *depth_render_target; 92 | 93 | std::vector dst_framebuffers; 94 | 95 | MaterialPipelineManager *material_pipeline_manager; 96 | 97 | Texture spot_light_shadow_default; 98 | 99 | vk::RenderPass render_pass; 100 | 101 | vk::DescriptorPool descriptor_pool; 102 | 103 | vk::DescriptorSetLayout descriptor_set_layout; 104 | vk::DescriptorSet descriptor_set; 105 | 106 | lavos::Buffer *matrix_uniform_buffer; 107 | lavos::Buffer *lighting_uniform_buffer; 108 | lavos::Buffer *camera_uniform_buffer; 109 | 110 | std::vector materials; 111 | std::vector sub_renderers; 112 | 113 | 114 | MaterialPipelineConfiguration CreateMaterialPipelineConfiguration(); 115 | 116 | void CreateFramebuffers(); 117 | 118 | void CleanupFramebuffers(); 119 | void CreateDescriptorPool(); 120 | 121 | void CreateDescriptorSetLayout(); 122 | void CreateDescriptorSet(); 123 | 124 | size_t GetLightingUniformBufferSize(); 125 | 126 | void CreateUniformBuffers(); 127 | 128 | void CreateRenderPasses(); 129 | void CleanupRenderPasses(); 130 | 131 | void CreateRenderCommandBuffer(); 132 | void CleanupRenderCommandBuffer(); 133 | 134 | protected: 135 | void RenderTargetChanged(RenderTarget *render_target) override; 136 | 137 | public: 138 | static const unsigned int max_spot_lights = 16; 139 | 140 | Renderer(Engine *engine, const RenderConfig &config, ColorRenderTarget *color_render_target, DepthRenderTarget *depth_render_target); 141 | ~Renderer(); 142 | 143 | Engine *GetEngine() const { return engine; } 144 | 145 | //vk::DescriptorPool GetDescriptorPool() const { return descriptor_pool; } 146 | 147 | void SetScene(Scene *scene) { this->scene = scene; } 148 | void SetCamera(Camera *camera) { this->camera = camera; } 149 | 150 | /** 151 | * Adds a SubRenderer to the Renderer. 152 | * The Renderer takes ownership of sub_renderer. 153 | */ 154 | void AddSubRenderer(SubRenderer *sub_renderer); 155 | 156 | /** 157 | * Removes a SubRenderer from the Renderer. 158 | * The ownership of sub_renderer is removed from the Renderer. 159 | */ 160 | void RemoveSubRenderer(SubRenderer *sub_renderer); 161 | 162 | void AddMaterial(Material *material); 163 | void RemoveMaterial(Material *material); 164 | 165 | void UpdateMatrixUniformBuffer(); 166 | void UpdateCameraUniformBuffer(); 167 | void UpdateLightingUniformBuffer(LightCollection *light_collection); 168 | void UpdateShadowDescriptors(LightCollection *light_collection); 169 | 170 | //MaterialPipeline GetMaterialPipeline(int index) { return material_pipelines[index]; } 171 | 172 | vk::RenderPass GetRenderPass() const { return render_pass; } 173 | 174 | bool GetAutoSetCameraAspect() const { return auto_set_camera_aspect; } 175 | void SetAutoSetCameraAspect(bool enabled) { auto_set_camera_aspect = enabled; } 176 | 177 | void DrawFrame(std::uint32_t image_index, 178 | std::vector wait_semaphores, 179 | std::vector wait_stages, 180 | std::vector signal_semaphores); 181 | 182 | void DrawFrameRecord(vk::CommandBuffer command_buffer, vk::Framebuffer dst_framebuffer); 183 | void RecordRenderables(vk::CommandBuffer command_buffer, 184 | Material::RenderMode render_mode, 185 | MaterialPipelineManager *material_pipeline_manager, 186 | vk::DescriptorSet renderer_descriptor_set); 187 | }; 188 | 189 | } 190 | 191 | #endif //VULKAN_RENDERER_H 192 | --------------------------------------------------------------------------------