-
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -11,3 +11,4 @@
|
||||
/cmake_install.cmake
|
||||
/libassets.a
|
||||
/resources.cpp
|
||||
/imgui.ini
|
||||
|
||||
@@ -1,8 +1,18 @@
|
||||
cmake_minimum_required(VERSION 3.13)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdata-sections -ffunction-sections")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdata-sections -ffunction-sections -DGLM_FORCE_DEPTH_ZERO_TO_ONE")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -UNDEBUG")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") # -rdynamic
|
||||
|
||||
# gprof
|
||||
# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pg")
|
||||
# set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pg")
|
||||
|
||||
# sanitizer
|
||||
# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address")
|
||||
#set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address")
|
||||
|
||||
# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined -fno-sanitize-recover=all -fsanitize=float-divide-by-zero -fsanitize=float-cast-overflow -fno-sanitize=null -fno-sanitize=alignment")
|
||||
|
||||
project (LuaVox VERSION 0.0 DESCRIPTION "LuaVox Description")
|
||||
add_executable(${PROJECT_NAME})
|
||||
target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_20)
|
||||
@@ -11,20 +21,41 @@ file(GLOB_RECURSE SOURCES RELATIVE ${PROJECT_SOURCE_DIR} "Src/*.cpp")
|
||||
target_sources(${PROJECT_NAME} PRIVATE ${SOURCES})
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC "${PROJECT_SOURCE_DIR}/Src")
|
||||
|
||||
include(FetchContent)
|
||||
|
||||
# Boost
|
||||
if(POLICY CMP0167)
|
||||
cmake_policy(SET CMP0167 NEW)
|
||||
endif()
|
||||
|
||||
set(Boost_USE_STATIC_LIBS ON)
|
||||
find_package(Boost REQUIRED COMPONENTS thread json)
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC ${Boost_INCLUDE_DIR})
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC Boost::thread Boost::json)
|
||||
# find_package(Boost REQUIRED COMPONENTS thread json)
|
||||
# target_include_directories(${PROJECT_NAME} PUBLIC ${Boost_INCLUDE_DIR})
|
||||
# target_link_libraries(${PROJECT_NAME} PUBLIC Boost::thread Boost::json)
|
||||
|
||||
set(BOOST_INCLUDE_LIBRARIES asio thread json)
|
||||
set(BOOST_ENABLE_CMAKE ON)
|
||||
FetchContent_Declare(
|
||||
Boost
|
||||
URL https://github.com/boostorg/boost/releases/download/boost-1.87.0/boost-1.87.0-cmake.7z
|
||||
USES_TERMINAL_DOWNLOAD TRUE
|
||||
DOWNLOAD_NO_EXTRACT FALSE
|
||||
)
|
||||
FetchContent_MakeAvailable(Boost)
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC Boost::asio Boost::thread Boost::json)
|
||||
|
||||
# glm
|
||||
find_package(glm REQUIRED)
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC ${GLM_INCLUDE_DIR})
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC ${GLM_LIBRARY})
|
||||
# find_package(glm REQUIRED)
|
||||
# target_include_directories(${PROJECT_NAME} PUBLIC ${GLM_INCLUDE_DIR})
|
||||
# target_link_libraries(${PROJECT_NAME} PUBLIC ${GLM_LIBRARY})
|
||||
|
||||
FetchContent_Declare(
|
||||
glm
|
||||
GIT_REPOSITORY https://github.com/g-truc/glm.git
|
||||
GIT_TAG 1.0.1
|
||||
)
|
||||
FetchContent_MakeAvailable(glm)
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC glm)
|
||||
|
||||
# JPEG
|
||||
find_package(JPEG REQUIRED)
|
||||
@@ -40,13 +71,26 @@ target_link_libraries(${PROJECT_NAME} PUBLIC PNG::PNG)
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC "${PROJECT_SOURCE_DIR}/Libs/png++")
|
||||
|
||||
# GLFW3
|
||||
find_package(glfw3 REQUIRED)
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC ${GLFW_INCLUDE_DIRS})
|
||||
# find_package(glfw3 REQUIRED)
|
||||
# target_include_directories(${PROJECT_NAME} PUBLIC ${GLFW_INCLUDE_DIRS})
|
||||
|
||||
FetchContent_Declare(
|
||||
glfw
|
||||
GIT_REPOSITORY https://github.com/glfw/glfw.git
|
||||
GIT_TAG 3.4
|
||||
)
|
||||
FetchContent_MakeAvailable(glfw)
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC glfw)
|
||||
|
||||
# FreeType
|
||||
find_package(Freetype REQUIRED)
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC ${GLM_INCLUDE_DIRS})
|
||||
# FetchContent_Declare(
|
||||
# freetype
|
||||
# GIT_REPOSITORY https://github.com/freetype/freetype.git
|
||||
# GIT_TAG freetype
|
||||
# )
|
||||
# FetchContent_MakeAvailable(freetype)
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC ${freetype_INCLUDE_DIRS})
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC Freetype::Freetype)
|
||||
|
||||
# ImGui
|
||||
@@ -70,5 +114,3 @@ SET_SOURCE_FILES_PROPERTIES(assets.o PROPERTIES EXTERNAL_OBJECT true GENERATED t
|
||||
add_library(assets STATIC resources.cpp assets.o)
|
||||
SET_TARGET_PROPERTIES(assets PROPERTIES LINKER_LANGUAGE C)
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC assets uring)
|
||||
|
||||
#set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fsanitize=address -fsanitize=undefined -fno-sanitize-recover=all -fsanitize=float-divide-by-zero -fsanitize=float-cast-overflow -fno-sanitize=null -fno-sanitize=alignment")
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
#include <Common/Abstract.hpp>
|
||||
|
||||
@@ -81,7 +82,7 @@ public:
|
||||
virtual void onDefEntityUpdates(const std::vector<DefEntityId_c> &updates) = 0;
|
||||
|
||||
// Сообщаем об изменившихся чанках
|
||||
virtual void onChunksChange(WorldId_c worldId, const std::vector<Pos::GlobalChunk> &changeOrAddList, const std::vector<Pos::GlobalChunk> &remove) = 0;
|
||||
virtual void onChunksChange(WorldId_c worldId, const std::unordered_set<Pos::GlobalChunk> &changeOrAddList, const std::unordered_set<Pos::GlobalChunk> &remove) = 0;
|
||||
// Установить позицию для камеры
|
||||
virtual void setCameraPos(WorldId_c worldId, Pos::Object pos, glm::quat quat) = 0;
|
||||
|
||||
@@ -90,7 +91,7 @@ public:
|
||||
|
||||
|
||||
struct Region {
|
||||
std::unordered_map<Pos::Local4_u::Key, Chunk[4][4][4]> Subs;
|
||||
std::unordered_map<Pos::Local16_u, Chunk> Chunks;
|
||||
};
|
||||
|
||||
|
||||
@@ -137,8 +138,8 @@ class IServerSession {
|
||||
public:
|
||||
struct {
|
||||
std::unordered_map<DefWorldId_c, DefWorldInfo> DefWorlds;
|
||||
std::unordered_map<DefVoxelId_c, VoxelInfo> DefVoxels;
|
||||
std::unordered_map<DefNodeId_c, NodeInfo> DefNodes;
|
||||
std::unordered_map<DefVoxelId_c, VoxelInfo> DefVoxels;
|
||||
std::unordered_map<DefNodeId_c, NodeInfo> DefNodes;
|
||||
std::unordered_map<DefPortalId_c, DefPortalInfo> DefPortals;
|
||||
std::unordered_map<DefEntityId_c, DefEntityInfo> DefEntityes;
|
||||
|
||||
@@ -147,6 +148,10 @@ public:
|
||||
std::unordered_map<EntityId_c, EntityInfo> Entityes;
|
||||
} Registry;
|
||||
|
||||
struct {
|
||||
std::unordered_map<WorldId_c, World> Worlds;
|
||||
} External;
|
||||
|
||||
virtual ~IServerSession();
|
||||
|
||||
virtual void atFreeDrawTime(GlobalTime gTime, float dTime) = 0;
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
#include <memory>
|
||||
#include <Common/Packets.hpp>
|
||||
#include <glm/ext.hpp>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
|
||||
|
||||
namespace LV::Client {
|
||||
@@ -163,6 +165,9 @@ void ServerSession::onCursorPosChange(int32_t width, int32_t height) {
|
||||
}
|
||||
|
||||
void ServerSession::onCursorMove(float xMove, float yMove) {
|
||||
xMove /= 10.f;
|
||||
yMove /= 10.f;
|
||||
|
||||
glm::vec3 deltaPYR;
|
||||
|
||||
static constexpr float PI = glm::pi<float>(), PI2 = PI*2, PI_HALF = PI/2, PI_DEG = PI/180;
|
||||
@@ -186,6 +191,26 @@ void ServerSession::onCursorBtn(ISurfaceEventListener::EnumCursorBtn btn, bool s
|
||||
void ServerSession::onKeyboardBtn(int btn, int state) {
|
||||
if(btn == GLFW_KEY_TAB && !state) {
|
||||
CursorMode = CursorMode == EnumCursorMoveMode::Default ? EnumCursorMoveMode::MoveAndHidden : EnumCursorMoveMode::Default;
|
||||
Keys.clear();
|
||||
}
|
||||
|
||||
|
||||
if(CursorMode == EnumCursorMoveMode::MoveAndHidden)
|
||||
{
|
||||
if(btn == GLFW_KEY_W)
|
||||
Keys.W = state;
|
||||
else if(btn == GLFW_KEY_A)
|
||||
Keys.A = state;
|
||||
else if(btn == GLFW_KEY_S)
|
||||
Keys.S = state;
|
||||
else if(btn == GLFW_KEY_D)
|
||||
Keys.D = state;
|
||||
else if(btn == GLFW_KEY_LEFT_SHIFT)
|
||||
Keys.SHIFT = state;
|
||||
else if(btn == GLFW_KEY_SPACE)
|
||||
Keys.SPACE = state;
|
||||
else if(btn == GLFW_KEY_LEFT_CONTROL)
|
||||
Keys.CTRL = state;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -196,17 +221,62 @@ void ServerSession::onJoystick() {
|
||||
void ServerSession::atFreeDrawTime(GlobalTime gTime, float dTime) {
|
||||
GTime = gTime;
|
||||
|
||||
Pos += glm::vec3(Speed) * dTime;
|
||||
Speed -= glm::dvec3(Speed) * double(dTime);
|
||||
|
||||
glm::mat4 rot(1);
|
||||
float deltaTime = 1-std::min<float>(gTime-PYR_At, 1/PYR_TIME_DELTA)*PYR_TIME_DELTA;
|
||||
rot = glm::rotate(rot, PYR.y-deltaTime*PYR_Offset.y, {0, 1, 0});
|
||||
|
||||
float mltpl = 16*dTime*Pos::Object_t::BS;
|
||||
if(Keys.CTRL)
|
||||
mltpl *= 16;
|
||||
|
||||
Speed += glm::vec3(rot*glm::vec4(0, 0, 1, 1)*float(Keys.W))*mltpl;
|
||||
Speed += glm::vec3(rot*glm::vec4(-1, 0, 0, 1)*float(Keys.A))*mltpl;
|
||||
Speed += glm::vec3(rot*glm::vec4(0, 0, -1, 1)*float(Keys.S))*mltpl;
|
||||
Speed += glm::vec3(rot*glm::vec4(1, 0, 0, 1)*float(Keys.D))*mltpl;
|
||||
Speed += glm::vec3(0, -1, 0)*float(Keys.SHIFT)*mltpl;
|
||||
Speed += glm::vec3(0, 1, 0)*float(Keys.SPACE)*mltpl;
|
||||
|
||||
{
|
||||
std::unordered_map<WorldId_c, std::tuple<std::unordered_set<Pos::GlobalChunk>, std::unordered_set<Pos::GlobalChunk>>> changeOrAddList_removeList;
|
||||
|
||||
// Пакеты
|
||||
ParsedPacket *pack;
|
||||
while(NetInputPackets.pop(pack)) {
|
||||
if(pack->Level1 == ToClient::L1::Content && ToClient::L2Content(pack->Level2) == ToClient::L2Content::ChunkVoxels) {
|
||||
PP_Content_ChunkVoxels &p = *dynamic_cast<PP_Content_ChunkVoxels*>(pack);
|
||||
Pos::GlobalRegion rPos(p.Pos.X >> 4, p.Pos.Y >> 4, p.Pos.Z >> 4);
|
||||
Pos::Local16_u cPos(p.Pos.X & 0xf, p.Pos.Y & 0xf, p.Pos.Z & 0xf);
|
||||
External.Worlds[p.Id].Regions[rPos].Chunks[cPos].Voxels = std::move(p.Cubes);
|
||||
|
||||
auto &pair = changeOrAddList_removeList[p.Id];
|
||||
std::get<0>(pair).insert(p.Pos);
|
||||
}
|
||||
|
||||
delete pack;
|
||||
}
|
||||
|
||||
if(RS && !changeOrAddList_removeList.empty()) {
|
||||
for(auto &pair : changeOrAddList_removeList) {
|
||||
RS->onChunksChange(pair.first, std::get<0>(pair.second), std::get<1>(pair.second));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!RS)
|
||||
return;
|
||||
|
||||
// Расчёт камеры
|
||||
{
|
||||
float deltaTime = 1-std::min<float>(gTime-PYR_At, 1/PYR_TIME_DELTA)*PYR_TIME_DELTA;
|
||||
glm::quat quat =
|
||||
glm::angleAxis(PYR.x-deltaTime*PYR_Offset.x, glm::vec3(1.f, 0.f, 0.f))
|
||||
* glm::angleAxis(PYR.y-deltaTime*PYR_Offset.y, glm::vec3(0.f, 1.f, 0.f));
|
||||
|
||||
RS->setCameraPos(0, {0, 0, 0}, quat);
|
||||
glm::quat quat =
|
||||
glm::angleAxis(PYR.x-deltaTime*PYR_Offset.x, glm::vec3(-1.f, 0.f, 0.f))
|
||||
* glm::angleAxis(PYR.y-deltaTime*PYR_Offset.y, glm::vec3(0.f, -1.f, 0.f));
|
||||
|
||||
RS->setCameraPos(0, Pos, quat);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -387,6 +457,7 @@ coro<> ServerSession::rP_Content(Net::AsyncSocket &sock) {
|
||||
Pos::GlobalChunk pos = *(Pos::GlobalChunk*) &posKey;
|
||||
|
||||
std::vector<VoxelCube> cubes(co_await sock.read<uint16_t>());
|
||||
uint16_t debugCubesCount = cubes.size();
|
||||
|
||||
for(size_t iter = 0; iter < cubes.size(); iter++) {
|
||||
VoxelCube &cube = cubes[iter];
|
||||
@@ -409,7 +480,7 @@ coro<> ServerSession::rP_Content(Net::AsyncSocket &sock) {
|
||||
|
||||
while(!NetInputPackets.push(packet));
|
||||
|
||||
LOG.info() << "Приняты воксели чанка " << int(wcId) << " / " << pos.X << ":" << pos.Y << ":" << pos.Z << " Вокселей " << cubes.size();
|
||||
LOG.info() << "Приняты воксели чанка " << int(wcId) << " / " << pos.X << ":" << pos.Y << ":" << pos.Z << " Вокселей " << debugCubesCount;
|
||||
|
||||
co_return;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "Abstract.hpp"
|
||||
#include "Common/Abstract.hpp"
|
||||
#include "Common/Async.hpp"
|
||||
#include "Common/Lockable.hpp"
|
||||
#include "Common/Net.hpp"
|
||||
@@ -31,10 +32,6 @@ class ServerSession : public AsyncObject, public IServerSession, public ISurface
|
||||
|
||||
TOS::Logger LOG = "ServerSession";
|
||||
|
||||
struct {
|
||||
glm::quat Quat;
|
||||
} Camera;
|
||||
|
||||
boost::lockfree::spsc_queue<ParsedPacket*> NetInputPackets;
|
||||
|
||||
// PYR - поворот камеры по осям xyz в радианах, PYR_Offset для сглаживание поворота
|
||||
@@ -43,6 +40,17 @@ class ServerSession : public AsyncObject, public IServerSession, public ISurface
|
||||
static constexpr float PYR_TIME_DELTA = 30;
|
||||
GlobalTime GTime;
|
||||
|
||||
struct {
|
||||
bool W = false, A = false, S = false, D = false, SHIFT = false, SPACE = false;
|
||||
bool CTRL = false;
|
||||
|
||||
void clear()
|
||||
{
|
||||
std::memset(this, 0, sizeof(*this));
|
||||
}
|
||||
} Keys;
|
||||
Pos::Object Pos = Pos::Object(0), Speed = Pos::Object(0);
|
||||
|
||||
public:
|
||||
// Нужен сокет, на котором только что был согласован игровой протокол (asyncInitGameProtocol)
|
||||
ServerSession(asio::io_context &ioc, std::unique_ptr<Net::AsyncSocket> &&socket, IRenderSession *rs = nullptr)
|
||||
|
||||
@@ -140,7 +140,7 @@ void Vulkan::run()
|
||||
while(!NeedShutdown)
|
||||
{
|
||||
float dTime = glfwGetTime()-prevTime;
|
||||
prevTime = glfwGetTime();
|
||||
prevTime += dTime;
|
||||
|
||||
Screen.State = DrawState::Begin;
|
||||
{
|
||||
@@ -176,15 +176,15 @@ void Vulkan::run()
|
||||
// Спрятать или показать курсор
|
||||
{
|
||||
int mode = glfwGetInputMode(Graphics.Window, GLFW_CURSOR);
|
||||
if(mode == GLFW_CURSOR_HIDDEN && sobj.CursorMode != ISurfaceEventListener::EnumCursorMoveMode::MoveAndHidden)
|
||||
if(mode == GLFW_CURSOR_DISABLED && sobj.CursorMode != ISurfaceEventListener::EnumCursorMoveMode::MoveAndHidden)
|
||||
glfwSetInputMode(Graphics.Window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
|
||||
else if(mode == GLFW_CURSOR_NORMAL && sobj.CursorMode != ISurfaceEventListener::EnumCursorMoveMode::Default) {
|
||||
glfwSetInputMode(Graphics.Window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
|
||||
glfwSetCursorPos(Graphics.Window, Screen.Width/2., Screen.Height/2.);
|
||||
Game.MLastPosX = Screen.Width/2.;
|
||||
Game.MLastPosY = Screen.Height/2.;
|
||||
glfwSetInputMode(Graphics.Window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// if(CallBeforeDraw)
|
||||
@@ -197,7 +197,8 @@ void Vulkan::run()
|
||||
glfwPollEvents();
|
||||
|
||||
VkResult err;
|
||||
err = vkAcquireNextImageKHR(Graphics.Device, Graphics.Swapchain, UINT64_MAX, SemaphoreImageAcquired, (VkFence) 0, &Graphics.DrawBufferCurrent);
|
||||
err = vkAcquireNextImageKHR(Graphics.Device, Graphics.Swapchain, 1000000000ULL/20, SemaphoreImageAcquired, (VkFence) 0, &Graphics.DrawBufferCurrent);
|
||||
GlobalTime gTime = glfwGetTime();
|
||||
|
||||
if (err == VK_ERROR_OUT_OF_DATE_KHR)
|
||||
{
|
||||
@@ -207,327 +208,325 @@ void Vulkan::run()
|
||||
} else if (err == VK_SUBOPTIMAL_KHR)
|
||||
{
|
||||
LOGGER.debug() << "VK_SUBOPTIMAL_KHR Pre";
|
||||
} else if(err == VK_SUCCESS) {
|
||||
|
||||
Screen.State = DrawState::Drawing;
|
||||
//Готовим инструкции рисовки
|
||||
{
|
||||
const VkCommandBufferBeginInfo cmd_buf_info =
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
|
||||
.pNext = nullptr,
|
||||
.flags = 0,
|
||||
.pInheritanceInfo = nullptr
|
||||
};
|
||||
|
||||
assert(!vkBeginCommandBuffer(Graphics.CommandBufferRender, &cmd_buf_info));
|
||||
}
|
||||
|
||||
{
|
||||
VkImageMemoryBarrier image_memory_barrier =
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||
.pNext = nullptr,
|
||||
.srcAccessMask = 0,
|
||||
.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
||||
.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.image = Graphics.DrawBuffers[Graphics.DrawBufferCurrent].Image, // Graphics.InlineTexture.Image,
|
||||
.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }
|
||||
};
|
||||
|
||||
vkCmdPipelineBarrier(Graphics.CommandBufferRender, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
||||
0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier);
|
||||
}
|
||||
|
||||
{
|
||||
const VkClearValue clear_values[2] =
|
||||
{
|
||||
[0] = { .color = { .float32 = { 0.1f, 0.1f, 0.1f, 1.f }}},
|
||||
[1] = { .depthStencil = { 1, 0 } },
|
||||
};
|
||||
|
||||
const VkRenderPassBeginInfo rp_begin =
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
|
||||
.pNext = nullptr,
|
||||
.renderPass = Graphics.RenderPass,
|
||||
.framebuffer = Graphics.DrawBuffers[Graphics.DrawBufferCurrent].FrameBuffer, //Graphics.InlineTexture.Frame,
|
||||
.renderArea = VkRect2D {
|
||||
.offset = {0, 0},
|
||||
.extent = Screen.FrameExtent
|
||||
},
|
||||
.clearValueCount = 2,
|
||||
.pClearValues = clear_values
|
||||
};
|
||||
|
||||
vkCmdBeginRenderPass(Graphics.CommandBufferRender, &rp_begin, VK_SUBPASS_CONTENTS_INLINE);
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
VkViewport viewport = { 0.f, 0.f, float(Screen.Width), float(Screen.Height), 0.f, 1.f };
|
||||
vkCmdSetViewport(Graphics.CommandBufferRender, 0, 1, &viewport);
|
||||
|
||||
VkRect2D scissor = { { int32_t(0), int32_t(0) }, { Screen.Width, Screen.Height } };
|
||||
vkCmdSetScissor(Graphics.CommandBufferRender, 0, 1, &scissor);
|
||||
}
|
||||
|
||||
if(Game.RSession) {
|
||||
auto &robj = *Game.RSession;
|
||||
// Рендер мира
|
||||
|
||||
robj.drawWorld(gTime, dTime, Graphics.CommandBufferRender);
|
||||
|
||||
uint16_t minSize = std::min(Screen.Width, Screen.Height);
|
||||
glm::ivec2 interfaceSize = {int(Screen.Width*720/minSize), int(Screen.Height*720/minSize)};
|
||||
}
|
||||
|
||||
// vkCmdEndRenderPass(Graphics.CommandBufferRender);
|
||||
|
||||
// {
|
||||
// VkImageMemoryBarrier src_barrier =
|
||||
// {
|
||||
// .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||
// .pNext = nullptr,
|
||||
// .srcAccessMask = 0,
|
||||
// .dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT,
|
||||
// .oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||
// .newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||
// .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
// .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
// .image = Graphics.InlineTexture.Image,
|
||||
// .subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }
|
||||
// };
|
||||
|
||||
// VkImageMemoryBarrier dst_barrier =
|
||||
// {
|
||||
// .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||
// .pNext = nullptr,
|
||||
// .srcAccessMask = 0,
|
||||
// .dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||
// .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
// .newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
// .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
// .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
// .image = Graphics.DrawBuffers[Graphics.DrawBufferCurrent].Image,
|
||||
// .subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }
|
||||
// };
|
||||
|
||||
// vkCmdPipelineBarrier(
|
||||
// Graphics.CommandBufferRender,
|
||||
// VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
// VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
// 0,
|
||||
// 0, nullptr,
|
||||
// 0, nullptr,
|
||||
// 1, &src_barrier
|
||||
// );
|
||||
|
||||
// vkCmdPipelineBarrier(
|
||||
// Graphics.CommandBufferRender,
|
||||
// VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
// VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
// 0,
|
||||
// 0, nullptr,
|
||||
// 0, nullptr,
|
||||
// 1, &dst_barrier
|
||||
// );
|
||||
|
||||
// VkImageCopy copy_region =
|
||||
// {
|
||||
// .srcSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1},
|
||||
// .srcOffset = {0, 0, 0},
|
||||
// .dstSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1},
|
||||
// .dstOffset = {0, 0, 0},
|
||||
// .extent = {Screen.FrameExtent.width, Screen.FrameExtent.height, 1}
|
||||
// };
|
||||
|
||||
// vkCmdCopyImage(
|
||||
// Graphics.CommandBufferRender,
|
||||
// Graphics.InlineTexture.Image,
|
||||
// VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||
// Graphics.DrawBuffers[Graphics.DrawBufferCurrent].Image,
|
||||
// VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
// 1, ©_region
|
||||
// );
|
||||
|
||||
// VkImageMemoryBarrier post_copy_barrier =
|
||||
// {
|
||||
// .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||
// .pNext = nullptr,
|
||||
// .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||
// .dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
||||
// .oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
// .newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||
// .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
// .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
// .image = Graphics.DrawBuffers[Graphics.DrawBufferCurrent].Image,
|
||||
// .subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }
|
||||
// };
|
||||
|
||||
// vkCmdPipelineBarrier(
|
||||
// Graphics.CommandBufferRender,
|
||||
// VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
// VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
||||
// 0,
|
||||
// 0, nullptr,
|
||||
// 0, nullptr,
|
||||
// 1, &post_copy_barrier
|
||||
// );
|
||||
// }
|
||||
|
||||
// {
|
||||
// VkImageMemoryBarrier prePresentBarrier =
|
||||
// {
|
||||
// .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||
// .pNext = nullptr,
|
||||
// .srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
||||
// .dstAccessMask = VK_ACCESS_MEMORY_READ_BIT,
|
||||
// .oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||
// .newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||
// .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
// .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
// .image = Graphics.InlineTexture.Image,
|
||||
// .subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }
|
||||
// };
|
||||
|
||||
// vkCmdPipelineBarrier(Graphics.CommandBufferRender, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
|
||||
// 0, 0, nullptr, 0, nullptr, 1, &prePresentBarrier);
|
||||
// }
|
||||
|
||||
// {
|
||||
// VkImageMemoryBarrier image_memory_barrier =
|
||||
// {
|
||||
// .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||
// .pNext = nullptr,
|
||||
// .srcAccessMask = 0,
|
||||
// .dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
||||
// .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
// .newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||
// .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
// .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
// .image = Graphics.DrawBuffers[Graphics.DrawBufferCurrent].Image,
|
||||
// .subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }
|
||||
// };
|
||||
|
||||
// vkCmdPipelineBarrier(Graphics.CommandBufferRender, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
||||
// 0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier);
|
||||
// }
|
||||
|
||||
// {
|
||||
// const VkClearValue clear_values[2] =
|
||||
// {
|
||||
// [0] = { .color = { .float32 = { 0.1f, 0.1f, 0.1f, 1.0f }}},
|
||||
// [1] = { .depthStencil = { 1, 0 } },
|
||||
// };
|
||||
|
||||
// const VkRenderPassBeginInfo rp_begin =
|
||||
// {
|
||||
// .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
|
||||
// .pNext = nullptr,
|
||||
// .renderPass = Graphics.RenderPass,
|
||||
// .framebuffer = Graphics.DrawBuffers[Graphics.DrawBufferCurrent].FrameBuffer,
|
||||
// .renderArea = VkRect2D {
|
||||
// .offset = {0, 0},
|
||||
// .extent = Screen.FrameExtent
|
||||
// },
|
||||
// .clearValueCount = 2,
|
||||
// .pClearValues = clear_values
|
||||
// };
|
||||
|
||||
// vkCmdBeginRenderPass(Graphics.CommandBufferRender, &rp_begin, VK_SUBPASS_CONTENTS_INLINE);
|
||||
// }
|
||||
|
||||
|
||||
|
||||
#ifdef HAS_IMGUI
|
||||
ImGui_ImplVulkan_NewFrame();
|
||||
ImGui_ImplGlfw_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
|
||||
ImGui::SetNextWindowPos({0, 0});
|
||||
ImGui::SetNextWindowSize({(float) Screen.Width, (float) Screen.Height});
|
||||
|
||||
assert(Game.ImGuiInterfaces.size());
|
||||
(this->*Game.ImGuiInterfaces.back())();
|
||||
|
||||
ImGui::Render();
|
||||
ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), Graphics.CommandBufferRender);
|
||||
#endif
|
||||
|
||||
vkCmdEndRenderPass(Graphics.CommandBufferRender);
|
||||
|
||||
{
|
||||
VkImageMemoryBarrier prePresentBarrier =
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||
.pNext = nullptr,
|
||||
.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
||||
.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT,
|
||||
.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||
.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
|
||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.image = Graphics.DrawBuffers[Graphics.DrawBufferCurrent].Image,
|
||||
.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }
|
||||
};
|
||||
|
||||
vkCmdPipelineBarrier(Graphics.CommandBufferRender, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
|
||||
0, 0, nullptr, 0, nullptr, 1, &prePresentBarrier);
|
||||
}
|
||||
|
||||
assert(!vkEndCommandBuffer(Graphics.CommandBufferRender));
|
||||
|
||||
{
|
||||
VkFence nullFence = VK_NULL_HANDLE;
|
||||
VkPipelineStageFlags pipe_stage_flags = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
|
||||
VkSubmitInfo submit_info =
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
|
||||
.pNext = nullptr,
|
||||
.waitSemaphoreCount = 1,
|
||||
.pWaitSemaphores = &SemaphoreImageAcquired,
|
||||
.pWaitDstStageMask = &pipe_stage_flags,
|
||||
.commandBufferCount = 1,
|
||||
.pCommandBuffers = &Graphics.CommandBufferRender,
|
||||
.signalSemaphoreCount = 1,
|
||||
.pSignalSemaphores = &SemaphoreDrawComplete
|
||||
};
|
||||
|
||||
//Рисуем, когда получим картинку
|
||||
assert(!vkQueueSubmit(Graphics.DeviceQueueGraphic, 1, &submit_info, nullFence));
|
||||
}
|
||||
|
||||
{
|
||||
VkPresentInfoKHR present =
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
|
||||
.pNext = NULL,
|
||||
.waitSemaphoreCount = 1,
|
||||
.pWaitSemaphores = &SemaphoreDrawComplete,
|
||||
.swapchainCount = 1,
|
||||
.pSwapchains = &Graphics.Swapchain,
|
||||
.pImageIndices = &Graphics.DrawBufferCurrent
|
||||
};
|
||||
|
||||
// Завершаем картинку
|
||||
err = vkQueuePresentKHR(Graphics.DeviceQueueGraphic, &present);
|
||||
if (err == VK_ERROR_OUT_OF_DATE_KHR)
|
||||
{
|
||||
freeSwapchains();
|
||||
buildSwapchains();
|
||||
} else if (err == VK_SUBOPTIMAL_KHR)
|
||||
LOGGER.debug() << "VK_SUBOPTIMAL_KHR Post";
|
||||
else
|
||||
assert(!err);
|
||||
}
|
||||
} else
|
||||
assert(!err);
|
||||
|
||||
|
||||
Screen.State = DrawState::Drawing;
|
||||
//Готовим инструкции рисовки
|
||||
{
|
||||
const VkCommandBufferBeginInfo cmd_buf_info =
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
|
||||
.pNext = nullptr,
|
||||
.flags = 0,
|
||||
.pInheritanceInfo = nullptr
|
||||
};
|
||||
|
||||
assert(!vkBeginCommandBuffer(Graphics.CommandBufferRender, &cmd_buf_info));
|
||||
}
|
||||
|
||||
{
|
||||
VkImageMemoryBarrier image_memory_barrier =
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||
.pNext = nullptr,
|
||||
.srcAccessMask = 0,
|
||||
.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
||||
.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.image = Graphics.DrawBuffers[Graphics.DrawBufferCurrent].Image, // Graphics.InlineTexture.Image,
|
||||
.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }
|
||||
};
|
||||
|
||||
vkCmdPipelineBarrier(Graphics.CommandBufferRender, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
||||
0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier);
|
||||
}
|
||||
|
||||
{
|
||||
const VkClearValue clear_values[2] =
|
||||
{
|
||||
[0] = { .color = { .float32 = { 0.1f, 0.1f, 0.1f, 1.f }}},
|
||||
[1] = { .depthStencil = { 1, 0 } },
|
||||
};
|
||||
|
||||
const VkRenderPassBeginInfo rp_begin =
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
|
||||
.pNext = nullptr,
|
||||
.renderPass = Graphics.RenderPass,
|
||||
.framebuffer = Graphics.DrawBuffers[Graphics.DrawBufferCurrent].FrameBuffer, //Graphics.InlineTexture.Frame,
|
||||
.renderArea = VkRect2D {
|
||||
.offset = {0, 0},
|
||||
.extent = Screen.FrameExtent
|
||||
},
|
||||
.clearValueCount = 2,
|
||||
.pClearValues = clear_values
|
||||
};
|
||||
|
||||
vkCmdBeginRenderPass(Graphics.CommandBufferRender, &rp_begin, VK_SUBPASS_CONTENTS_INLINE);
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
VkViewport viewport = { 0.f, 0.f, float(Screen.Width), float(Screen.Height), 0.f, 1.f };
|
||||
vkCmdSetViewport(Graphics.CommandBufferRender, 0, 1, &viewport);
|
||||
|
||||
VkRect2D scissor = { { int32_t(0), int32_t(0) }, { Screen.Width, Screen.Height } };
|
||||
vkCmdSetScissor(Graphics.CommandBufferRender, 0, 1, &scissor);
|
||||
}
|
||||
|
||||
GlobalTime gTime = glfwGetTime();
|
||||
|
||||
if(Game.RSession) {
|
||||
auto &robj = *Game.RSession;
|
||||
// Рендер мира
|
||||
|
||||
robj.drawWorld(gTime, dTime, Graphics.CommandBufferRender);
|
||||
|
||||
uint16_t minSize = std::min(Screen.Width, Screen.Height);
|
||||
glm::ivec2 interfaceSize = {int(Screen.Width*720/minSize), int(Screen.Height*720/minSize)};
|
||||
}
|
||||
|
||||
// vkCmdEndRenderPass(Graphics.CommandBufferRender);
|
||||
|
||||
// {
|
||||
// VkImageMemoryBarrier src_barrier =
|
||||
// {
|
||||
// .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||
// .pNext = nullptr,
|
||||
// .srcAccessMask = 0,
|
||||
// .dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT,
|
||||
// .oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||
// .newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||
// .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
// .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
// .image = Graphics.InlineTexture.Image,
|
||||
// .subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }
|
||||
// };
|
||||
|
||||
// VkImageMemoryBarrier dst_barrier =
|
||||
// {
|
||||
// .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||
// .pNext = nullptr,
|
||||
// .srcAccessMask = 0,
|
||||
// .dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||
// .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
// .newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
// .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
// .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
// .image = Graphics.DrawBuffers[Graphics.DrawBufferCurrent].Image,
|
||||
// .subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }
|
||||
// };
|
||||
|
||||
// vkCmdPipelineBarrier(
|
||||
// Graphics.CommandBufferRender,
|
||||
// VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
// VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
// 0,
|
||||
// 0, nullptr,
|
||||
// 0, nullptr,
|
||||
// 1, &src_barrier
|
||||
// );
|
||||
|
||||
// vkCmdPipelineBarrier(
|
||||
// Graphics.CommandBufferRender,
|
||||
// VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
// VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
// 0,
|
||||
// 0, nullptr,
|
||||
// 0, nullptr,
|
||||
// 1, &dst_barrier
|
||||
// );
|
||||
|
||||
// VkImageCopy copy_region =
|
||||
// {
|
||||
// .srcSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1},
|
||||
// .srcOffset = {0, 0, 0},
|
||||
// .dstSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1},
|
||||
// .dstOffset = {0, 0, 0},
|
||||
// .extent = {Screen.FrameExtent.width, Screen.FrameExtent.height, 1}
|
||||
// };
|
||||
|
||||
// vkCmdCopyImage(
|
||||
// Graphics.CommandBufferRender,
|
||||
// Graphics.InlineTexture.Image,
|
||||
// VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||
// Graphics.DrawBuffers[Graphics.DrawBufferCurrent].Image,
|
||||
// VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
// 1, ©_region
|
||||
// );
|
||||
|
||||
// VkImageMemoryBarrier post_copy_barrier =
|
||||
// {
|
||||
// .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||
// .pNext = nullptr,
|
||||
// .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||
// .dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
||||
// .oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
// .newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||
// .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
// .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
// .image = Graphics.DrawBuffers[Graphics.DrawBufferCurrent].Image,
|
||||
// .subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }
|
||||
// };
|
||||
|
||||
// vkCmdPipelineBarrier(
|
||||
// Graphics.CommandBufferRender,
|
||||
// VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
// VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
||||
// 0,
|
||||
// 0, nullptr,
|
||||
// 0, nullptr,
|
||||
// 1, &post_copy_barrier
|
||||
// );
|
||||
// }
|
||||
|
||||
// {
|
||||
// VkImageMemoryBarrier prePresentBarrier =
|
||||
// {
|
||||
// .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||
// .pNext = nullptr,
|
||||
// .srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
||||
// .dstAccessMask = VK_ACCESS_MEMORY_READ_BIT,
|
||||
// .oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||
// .newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||
// .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
// .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
// .image = Graphics.InlineTexture.Image,
|
||||
// .subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }
|
||||
// };
|
||||
|
||||
// vkCmdPipelineBarrier(Graphics.CommandBufferRender, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
|
||||
// 0, 0, nullptr, 0, nullptr, 1, &prePresentBarrier);
|
||||
// }
|
||||
|
||||
// {
|
||||
// VkImageMemoryBarrier image_memory_barrier =
|
||||
// {
|
||||
// .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||
// .pNext = nullptr,
|
||||
// .srcAccessMask = 0,
|
||||
// .dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
||||
// .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
// .newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||
// .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
// .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
// .image = Graphics.DrawBuffers[Graphics.DrawBufferCurrent].Image,
|
||||
// .subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }
|
||||
// };
|
||||
|
||||
// vkCmdPipelineBarrier(Graphics.CommandBufferRender, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
||||
// 0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier);
|
||||
// }
|
||||
|
||||
// {
|
||||
// const VkClearValue clear_values[2] =
|
||||
// {
|
||||
// [0] = { .color = { .float32 = { 0.1f, 0.1f, 0.1f, 1.0f }}},
|
||||
// [1] = { .depthStencil = { 1, 0 } },
|
||||
// };
|
||||
|
||||
// const VkRenderPassBeginInfo rp_begin =
|
||||
// {
|
||||
// .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
|
||||
// .pNext = nullptr,
|
||||
// .renderPass = Graphics.RenderPass,
|
||||
// .framebuffer = Graphics.DrawBuffers[Graphics.DrawBufferCurrent].FrameBuffer,
|
||||
// .renderArea = VkRect2D {
|
||||
// .offset = {0, 0},
|
||||
// .extent = Screen.FrameExtent
|
||||
// },
|
||||
// .clearValueCount = 2,
|
||||
// .pClearValues = clear_values
|
||||
// };
|
||||
|
||||
// vkCmdBeginRenderPass(Graphics.CommandBufferRender, &rp_begin, VK_SUBPASS_CONTENTS_INLINE);
|
||||
// }
|
||||
|
||||
|
||||
|
||||
#ifdef HAS_IMGUI
|
||||
ImGui_ImplVulkan_NewFrame();
|
||||
ImGui_ImplGlfw_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
|
||||
ImGui::SetNextWindowPos({0, 0});
|
||||
ImGui::SetNextWindowSize({(float) Screen.Width, (float) Screen.Height});
|
||||
|
||||
assert(Game.ImGuiInterfaces.size());
|
||||
(this->*Game.ImGuiInterfaces.back())();
|
||||
|
||||
ImGui::Render();
|
||||
ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), Graphics.CommandBufferRender);
|
||||
#endif
|
||||
|
||||
vkCmdEndRenderPass(Graphics.CommandBufferRender);
|
||||
|
||||
{
|
||||
VkImageMemoryBarrier prePresentBarrier =
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||
.pNext = nullptr,
|
||||
.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
||||
.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT,
|
||||
.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||
.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
|
||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.image = Graphics.DrawBuffers[Graphics.DrawBufferCurrent].Image,
|
||||
.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }
|
||||
};
|
||||
|
||||
vkCmdPipelineBarrier(Graphics.CommandBufferRender, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
|
||||
0, 0, nullptr, 0, nullptr, 1, &prePresentBarrier);
|
||||
}
|
||||
|
||||
assert(!vkEndCommandBuffer(Graphics.CommandBufferRender));
|
||||
|
||||
{
|
||||
VkFence nullFence = VK_NULL_HANDLE;
|
||||
VkPipelineStageFlags pipe_stage_flags = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
|
||||
VkSubmitInfo submit_info =
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
|
||||
.pNext = nullptr,
|
||||
.waitSemaphoreCount = 1,
|
||||
.pWaitSemaphores = &SemaphoreImageAcquired,
|
||||
.pWaitDstStageMask = &pipe_stage_flags,
|
||||
.commandBufferCount = 1,
|
||||
.pCommandBuffers = &Graphics.CommandBufferRender,
|
||||
.signalSemaphoreCount = 1,
|
||||
.pSignalSemaphores = &SemaphoreDrawComplete
|
||||
};
|
||||
|
||||
//Рисуем, когда получим картинку
|
||||
assert(!vkQueueSubmit(Graphics.DeviceQueueGraphic, 1, &submit_info, nullFence));
|
||||
}
|
||||
|
||||
{
|
||||
VkPresentInfoKHR present =
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
|
||||
.pNext = NULL,
|
||||
.waitSemaphoreCount = 1,
|
||||
.pWaitSemaphores = &SemaphoreDrawComplete,
|
||||
.swapchainCount = 1,
|
||||
.pSwapchains = &Graphics.Swapchain,
|
||||
.pImageIndices = &Graphics.DrawBufferCurrent
|
||||
};
|
||||
|
||||
// Завершаем картинку
|
||||
err = vkQueuePresentKHR(Graphics.DeviceQueueGraphic, &present);
|
||||
if (err == VK_ERROR_OUT_OF_DATE_KHR)
|
||||
{
|
||||
freeSwapchains();
|
||||
buildSwapchains();
|
||||
} else if (err == VK_SUBOPTIMAL_KHR)
|
||||
LOGGER.debug() << "VK_SUBOPTIMAL_KHR Post";
|
||||
else
|
||||
assert(!err);
|
||||
}
|
||||
assert(err == VK_TIMEOUT);
|
||||
|
||||
if(Game.Session) {
|
||||
Game.Session->atFreeDrawTime(gTime, dTime);
|
||||
@@ -996,8 +995,15 @@ void Vulkan::glfwCallbackOnResize(GLFWwindow *window, int width, int height)
|
||||
handler->freeSwapchains();
|
||||
handler->buildSwapchains();
|
||||
|
||||
if(handler->Game.Session)
|
||||
if(handler->Game.Session) {
|
||||
handler->Game.Session->onResize(width, height);
|
||||
|
||||
if(handler->Game.Session->CursorMode == ISurfaceEventListener::EnumCursorMoveMode::MoveAndHidden) {
|
||||
glfwSetCursorPos(window, width/2., height/2.);
|
||||
handler->Game.MLastPosX = width/2.;
|
||||
handler->Game.MLastPosY = height/2.;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1018,8 +1024,9 @@ void Vulkan::glfwCallbackOnCursorPos(GLFWwindow* window, double xpos, double ypo
|
||||
if(sobj.CursorMode == ISurfaceEventListener::EnumCursorMoveMode::Default) {
|
||||
sobj.onCursorPosChange((int32_t) xpos, (int32_t) ypos);
|
||||
} else {
|
||||
glfwSetCursorPos(handler->Graphics.Window, handler->Screen.Width/2., handler->Screen.Height/2.);
|
||||
sobj.onCursorMove(xpos-handler->Screen.Width/2., handler->Screen.Height/2.-ypos);
|
||||
sobj.onCursorMove(xpos-handler->Game.MLastPosX, handler->Game.MLastPosY-ypos);
|
||||
handler->Game.MLastPosX = xpos;
|
||||
handler->Game.MLastPosY = ypos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,9 +16,7 @@
|
||||
|
||||
#define HAS_IMGUI
|
||||
|
||||
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
|
||||
|
||||
#include <freetype/freetype.h>
|
||||
#include "freetype/freetype.h"
|
||||
|
||||
#include <vulkan/vulkan_core.h>
|
||||
#include <glm/ext.hpp>
|
||||
@@ -28,6 +26,8 @@
|
||||
#define GLFW_INCLUDE_NONE
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
static_assert(GLM_CONFIG_CLIP_CONTROL == GLM_CLIP_CONTROL_RH_ZO);
|
||||
|
||||
#define IMGUI_ENABLE_STB_TEXTEDIT_UNICODE
|
||||
|
||||
namespace LV::Client::VK {
|
||||
@@ -245,6 +245,8 @@ public:
|
||||
|
||||
std::list<void (Vulkan::*)()> ImGuiInterfaces;
|
||||
std::unique_ptr<ServerObj> Server;
|
||||
|
||||
double MLastPosX, MLastPosY;
|
||||
} Game;
|
||||
|
||||
private:
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
#include "VulkanRenderSession.hpp"
|
||||
#include "Client/Vulkan/Vulkan.hpp"
|
||||
#include "Common/Abstract.hpp"
|
||||
#include "assets.hpp"
|
||||
#include <glm/ext/matrix_transform.hpp>
|
||||
#include <memory>
|
||||
#include <vulkan/vulkan_core.h>
|
||||
#include <fstream>
|
||||
|
||||
namespace LV::Client::VK {
|
||||
|
||||
@@ -92,7 +94,7 @@ void VulkanRenderSession::init(Vulkan *instance) {
|
||||
.binding = 1,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||
.descriptorCount = 1,
|
||||
.stageFlags = VK_SHADER_STAGE_VERTEX_BIT,
|
||||
.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||
.pImmutableSamplers = nullptr
|
||||
}
|
||||
};
|
||||
@@ -136,7 +138,7 @@ void VulkanRenderSession::init(Vulkan *instance) {
|
||||
.binding = 1,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||
.descriptorCount = 1,
|
||||
.stageFlags = VK_SHADER_STAGE_VERTEX_BIT,
|
||||
.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||
.pImmutableSamplers = nullptr
|
||||
}
|
||||
};
|
||||
@@ -188,13 +190,28 @@ void VulkanRenderSession::init(Vulkan *instance) {
|
||||
return true;
|
||||
});
|
||||
|
||||
int width, height;
|
||||
bool hasAlpha;
|
||||
ByteBuffer image = VK::loadPNG(std::ifstream("/home/mr_s/Workspace/Alpha/LuaVox/assets/grass.png"), width, height, hasAlpha);
|
||||
uint16_t texId = VKCTX->MainTest.atlasAddTexture(width, height);
|
||||
VKCTX->MainTest.atlasChangeTextureData(texId, (const uint32_t*) image.data());
|
||||
|
||||
/*
|
||||
x left -1 ~ right 1
|
||||
y up -1 ~ down 1
|
||||
z far 1 ~ near 0
|
||||
|
||||
glm
|
||||
|
||||
*/
|
||||
|
||||
NodeVertexStatic *array = (NodeVertexStatic*) VKCTX->TestQuad.mapMemory();
|
||||
array[0] = {112, 114, 113, 0, 0, 0, 0, 0, 0};
|
||||
array[1] = {114, 114, 113, 0, 0, 0, 0, 65535, 0};
|
||||
array[2] = {114, 112, 113, 0, 0, 0, 0, 65535, 65535};
|
||||
array[3] = {112, 114, 113, 0, 0, 0, 0, 0, 0};
|
||||
array[4] = {114, 112, 113, 0, 0, 0, 0, 65535, 65535};
|
||||
array[5] = {112, 112, 113, 0, 0, 0, 0, 0, 65535};
|
||||
array[0] = {112, 114, 50, 0, 0, 0, 0, 0, 0};
|
||||
array[1] = {114, 114, 50, 0, 0, 0, 0, 65535, 0};
|
||||
array[2] = {114, 112, 50, 0, 0, 0, 0, 65535, 65535};
|
||||
array[3] = {112, 114, 50, 0, 0, 0, 0, 0, 0};
|
||||
array[4] = {114, 112, 50, 0, 0, 0, 0, 65535, 65535};
|
||||
array[5] = {112, 112, 50, 0, 0, 0, 0, 0, 65535};
|
||||
VKCTX->TestQuad.unMapMemory();
|
||||
}
|
||||
|
||||
@@ -576,8 +593,32 @@ void VulkanRenderSession::onDefEntityUpdates(const std::vector<DefEntityId_c> &u
|
||||
|
||||
}
|
||||
|
||||
void VulkanRenderSession::onChunksChange(WorldId_c worldId, const std::vector<Pos::GlobalChunk> &changeOrAddList, const std::vector<Pos::GlobalChunk> &remove) {
|
||||
void VulkanRenderSession::onChunksChange(WorldId_c worldId, const std::unordered_set<Pos::GlobalChunk> &changeOrAddList, const std::unordered_set<Pos::GlobalChunk> &remove) {
|
||||
for(Pos::GlobalChunk pos : changeOrAddList) {
|
||||
Pos::GlobalRegion rPos(pos.X >> 4, pos.Y >> 4, pos.Z >> 4);
|
||||
Pos::Local16_u cPos(pos.X & 0xf, pos.Y & 0xf, pos.Z & 0xf);
|
||||
|
||||
const auto &voxels = ServerSession->External.Worlds[worldId].Regions[rPos].Chunks[cPos].Voxels;
|
||||
auto &table = External.ChunkVoxelMesh[worldId];
|
||||
|
||||
if(voxels.empty()) {
|
||||
auto iter = table.find(pos);
|
||||
if(iter != table.end())
|
||||
table.erase(iter);
|
||||
|
||||
if(table.empty())
|
||||
External.ChunkVoxelMesh.erase(External.ChunkVoxelMesh.find(worldId));
|
||||
} else {
|
||||
auto &buffer = table[pos] = std::make_unique<Buffer>(VkInst, voxels.size()*6*6*sizeof(NodeVertexStatic));
|
||||
NodeVertexStatic *vertex = (NodeVertexStatic*) buffer->mapMemory();
|
||||
|
||||
for(const VoxelCube &cube : voxels) {
|
||||
|
||||
}
|
||||
|
||||
buffer->unMapMemory();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VulkanRenderSession::setCameraPos(WorldId_c worldId, Pos::Object pos, glm::quat quat) {
|
||||
@@ -587,14 +628,19 @@ void VulkanRenderSession::setCameraPos(WorldId_c worldId, Pos::Object pos, glm::
|
||||
}
|
||||
|
||||
void VulkanRenderSession::beforeDraw() {
|
||||
|
||||
if(VKCTX) {
|
||||
VKCTX->MainTest.atlasUpdateDynamicData();
|
||||
VKCTX->LightDummy.atlasUpdateDynamicData();
|
||||
}
|
||||
}
|
||||
|
||||
void VulkanRenderSession::drawWorld(GlobalTime gTime, float dTime, VkCommandBuffer drawCmd) {
|
||||
glm::mat4 proj = glm::perspective<float>(75, float(VkInst->Screen.Width)/float(VkInst->Screen.Height), 0.5, std::pow(2, 17));
|
||||
PCO.ProjView = glm::mat4(Quat);
|
||||
//PCO.ProjView *= proj;
|
||||
PCO.Model = glm::mat4(1); //= glm::rotate(glm::mat4(1), float(gTime/10), glm::vec3(0, 1, 0));
|
||||
// Сместить в координаты игрока, повернуть относительно взгляда, ещё поворот на 180 и проецировать на экран
|
||||
PCO.ProjView = glm::mat4(1);
|
||||
PCO.ProjView = glm::translate(PCO.ProjView, -glm::vec3(Pos)/float(Pos::Object_t::BS));
|
||||
PCO.ProjView = proj*glm::mat4(Quat)*glm::rotate(glm::mat4(1), glm::pi<float>(), glm::vec3(0, 1, 0))*PCO.ProjView;
|
||||
PCO.Model = glm::mat4(1);
|
||||
|
||||
vkCmdBindPipeline(drawCmd, VK_PIPELINE_BIND_POINT_GRAPHICS, NodeStaticOpaquePipeline);
|
||||
vkCmdPushConstants(drawCmd, MainAtlas_LightMap_PipelineLayout,
|
||||
@@ -606,7 +652,14 @@ void VulkanRenderSession::drawWorld(GlobalTime gTime, float dTime, VkCommandBuff
|
||||
VkDeviceSize vkOffsets = 0;
|
||||
VkBuffer vkBuffer = VKCTX->TestQuad;
|
||||
vkCmdBindVertexBuffers(drawCmd, 0, 1, &vkBuffer, &vkOffsets);
|
||||
vkCmdDraw(drawCmd, 6, 1, 0, 0);
|
||||
|
||||
for(int i = 0; i < 16; i++) {
|
||||
PCO.Model = glm::rotate(PCO.Model, glm::half_pi<float>()*i/4, glm::vec3(0, 1, 0));
|
||||
vkCmdPushConstants(drawCmd, MainAtlas_LightMap_PipelineLayout,
|
||||
VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_GEOMETRY_BIT, 0, sizeof(WorldPCO), &PCO);
|
||||
vkCmdDraw(drawCmd, 6, 1, 0, 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void VulkanRenderSession::updateDescriptor_MainAtlas() {
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "Client/Abstract.hpp"
|
||||
#include "Common/Abstract.hpp"
|
||||
#include <Client/Vulkan/Vulkan.hpp>
|
||||
#include <glm/ext/matrix_transform.hpp>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
|
||||
/*
|
||||
У движка есть один текстурный атлас VK_IMAGE_VIEW_TYPE_2D_ARRAY(RGBA_UINT) и к нему Storage с инфой о положении текстур
|
||||
Это общий для всех VkDescriptorSetLayout и VkDescriptorSet
|
||||
@@ -127,6 +130,10 @@ class VulkanRenderSession : public IRenderSession, public IVulkanDependent {
|
||||
|
||||
std::map<TextureId_c, uint16_t> ServerToAtlas;
|
||||
|
||||
struct {
|
||||
std::unordered_map<WorldId_c, std::unordered_map<Pos::GlobalChunk, std::unique_ptr<Buffer>>> ChunkVoxelMesh;
|
||||
} External;
|
||||
|
||||
virtual void free(Vulkan *instance) override;
|
||||
virtual void init(Vulkan *instance) override;
|
||||
|
||||
@@ -153,7 +160,7 @@ public:
|
||||
virtual void onDefPortalUpdates(const std::vector<DefPortalId_c> &updates) override;
|
||||
virtual void onDefEntityUpdates(const std::vector<DefEntityId_c> &updates) override;
|
||||
|
||||
virtual void onChunksChange(WorldId_c worldId, const std::vector<Pos::GlobalChunk> &changeOrAddList, const std::vector<Pos::GlobalChunk> &remove) override;
|
||||
virtual void onChunksChange(WorldId_c worldId, const std::unordered_set<Pos::GlobalChunk> &changeOrAddList, const std::unordered_set<Pos::GlobalChunk> &remove) override;
|
||||
virtual void setCameraPos(WorldId_c worldId, Pos::Object pos, glm::quat quat) override;
|
||||
|
||||
glm::mat4 calcViewMatrix(glm::quat quat, glm::vec3 camOffset = glm::vec3(0)) {
|
||||
|
||||
@@ -8,10 +8,12 @@
|
||||
#include <chrono>
|
||||
#include <glm/geometric.hpp>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include "SaveBackends/Filesystem.hpp"
|
||||
#include "Server/SaveBackend.hpp"
|
||||
|
||||
namespace LV::Server {
|
||||
|
||||
@@ -27,9 +29,10 @@ static thread_local std::vector<ContentViewCircle> TL_Circles;
|
||||
|
||||
std::vector<ContentViewCircle> GameServer::WorldObj::calcCVCs(ContentViewCircle circle, int depth)
|
||||
{
|
||||
TL_Circles.reserve(4096);
|
||||
TL_Circles.clear();
|
||||
TL_Circles.reserve(256);
|
||||
TL_Circles.push_back(circle);
|
||||
_calcContentViewCircles(TL_Circles.front(), depth);
|
||||
_calcContentViewCircles(circle, depth);
|
||||
return TL_Circles;
|
||||
}
|
||||
|
||||
@@ -215,6 +218,42 @@ coro<> GameServer::pushSocketGameProtocol(tcp::socket socket, const std::string
|
||||
}
|
||||
}
|
||||
|
||||
Region* GameServer::forceGetRegion(WorldId_t worldId, Pos::GlobalRegion pos) {
|
||||
auto worldIter = Expanse.Worlds.find(worldId);
|
||||
assert(worldIter != Expanse.Worlds.end());
|
||||
World &world = *worldIter->second;
|
||||
|
||||
auto iterRegion = world.Regions.find(pos);
|
||||
if(iterRegion == world.Regions.end() || !iterRegion->second->IsLoaded) {
|
||||
std::unique_ptr<Region> ®ion = world.Regions[pos];
|
||||
|
||||
if(!region)
|
||||
region = std::make_unique<Region>();
|
||||
|
||||
std::string worldName = "world_"+std::to_string(worldId);
|
||||
if(SaveBackend.World->isExist(worldName, pos)) {
|
||||
SB_Region data;
|
||||
SaveBackend.World->load(worldName, pos, &data);
|
||||
|
||||
region->IsLoaded = true;
|
||||
region->load(&data);
|
||||
} else {
|
||||
region->IsLoaded = true;
|
||||
if(pos.Y == 0) {
|
||||
for(int z = 0; z < 16; z++)
|
||||
for(int x = 0; x < 16; x++) {
|
||||
region->Voxels[x][0][z].push_back({{0, 0, 0}, {255, 255, 255}, 0});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::fill(region->IsChunkChanged_Voxels, region->IsChunkChanged_Voxels+64, ~0);
|
||||
return region.get();
|
||||
} else {
|
||||
return iterRegion->second.get();
|
||||
}
|
||||
}
|
||||
|
||||
void GameServer::init(fs::path worldPath) {
|
||||
Expanse.Worlds[0] = std::make_unique<World>(0);
|
||||
|
||||
@@ -302,16 +341,16 @@ void GameServer::run() {
|
||||
// Сон или подгонка длительности такта при высоких нагрузках
|
||||
std::chrono::steady_clock::time_point atTickEnd = std::chrono::steady_clock::now();
|
||||
float currentWastedTime = double((atTickEnd-atTickStart).count() * std::chrono::steady_clock::duration::period::num) / std::chrono::steady_clock::duration::period::den;
|
||||
float freeTime = CurrentTickDuration-currentWastedTime-GlobalTickLagTime;
|
||||
GlobalTickLagTime += CurrentTickDuration-currentWastedTime;
|
||||
|
||||
if(freeTime > 0) {
|
||||
if(GlobalTickLagTime > 0) {
|
||||
CurrentTickDuration -= PerTickAdjustment;
|
||||
if(CurrentTickDuration < PerTickDuration)
|
||||
CurrentTickDuration = PerTickDuration;
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(uint32_t(1000*freeTime)));
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(uint32_t(1000*GlobalTickLagTime)));
|
||||
GlobalTickLagTime = 0;
|
||||
} else {
|
||||
GlobalTickLagTime = freeTime;
|
||||
CurrentTickDuration += PerTickAdjustment;
|
||||
}
|
||||
}
|
||||
@@ -558,7 +597,7 @@ void GameServer::stepWorlds() {
|
||||
|
||||
if(rPos != pRegion.first || pWorld.first != entity.WorldId) {
|
||||
|
||||
Region *toRegion = Expanse.Worlds[entity.WorldId]->forceLoadOrGetRegion(rPos);
|
||||
Region *toRegion = forceGetRegion(entity.WorldId, rPos);
|
||||
LocalEntityId_t newId = toRegion->pushEntity(entity);
|
||||
// toRegion->Entityes[newId].WorldId = Если мир изменился
|
||||
|
||||
@@ -808,6 +847,11 @@ void GameServer::stepWorlds() {
|
||||
if(needToUnload) {
|
||||
regionsToRemove.push_back(pRegion.first);
|
||||
}
|
||||
|
||||
// Сброс информации об изменившихся данных
|
||||
|
||||
std::fill(region.IsChunkChanged_Voxels, region.IsChunkChanged_Voxels+64, 0);
|
||||
std::fill(region.IsChunkChanged_Nodes, region.IsChunkChanged_Nodes+64, 0);
|
||||
}
|
||||
|
||||
for(Pos::GlobalRegion regionPos : regionsToRemove) {
|
||||
@@ -962,7 +1006,13 @@ void GameServer::stepSendPlayersPackets() {
|
||||
}
|
||||
|
||||
void GameServer::stepLoadRegions() {
|
||||
for(auto &iterWorld : Expanse.Worlds) {
|
||||
for(Pos::GlobalRegion pos : iterWorld.second->NeedToLoad) {
|
||||
forceGetRegion(iterWorld.first, pos);
|
||||
}
|
||||
|
||||
iterWorld.second->NeedToLoad.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void GameServer::stepGlobal() {
|
||||
|
||||
@@ -134,6 +134,9 @@ public:
|
||||
// Инициализация игрового протокола для сокета (onSocketAuthorized() может передать сокет в onSocketGame())
|
||||
coro<> pushSocketGameProtocol(tcp::socket socket, const std::string username);
|
||||
|
||||
/* Загрузит, сгенерирует или просто выдаст регион из мира, который должен существовать */
|
||||
Region* forceGetRegion(WorldId_t worldId, Pos::GlobalRegion pos);
|
||||
|
||||
private:
|
||||
void init(fs::path worldPath);
|
||||
void prerun();
|
||||
|
||||
@@ -16,6 +16,7 @@ struct SB_Region {
|
||||
std::unordered_map<Pos::Local16_u, Node> Nodes;
|
||||
std::unordered_map<DefNodeId_t, std::string> NodeMap;
|
||||
std::vector<Entity> Entityes;
|
||||
std::unordered_map<DefEntityId_t, std::string> EntityMap;
|
||||
};
|
||||
|
||||
class IWorldSaveBackend {
|
||||
|
||||
@@ -46,17 +46,4 @@ void World::onCEC_RegionsLost(ContentEventController *cec, const std::vector<Pos
|
||||
}
|
||||
}
|
||||
|
||||
Region* World::forceLoadOrGetRegion(Pos::GlobalRegion pos) {
|
||||
std::unique_ptr<Region> ®ion = Regions[pos];
|
||||
if(!region)
|
||||
region = std::make_unique<Region>();
|
||||
|
||||
if(!region->IsLoaded) {
|
||||
region->IsLoaded = true;
|
||||
}
|
||||
|
||||
return region.get();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -3,8 +3,10 @@
|
||||
#include "Common/Abstract.hpp"
|
||||
#include "Server/Abstract.hpp"
|
||||
#include "Server/ContentEventController.hpp"
|
||||
#include "Server/SaveBackend.hpp"
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
|
||||
namespace LV::Server {
|
||||
@@ -15,7 +17,7 @@ class Region {
|
||||
public:
|
||||
uint64_t IsChunkChanged_Voxels[64] = {0};
|
||||
uint64_t IsChunkChanged_Nodes[64] = {0};
|
||||
bool IsChanged = false;
|
||||
bool IsChanged = false; // Изменён ли был регион, относительно последнего сохранения
|
||||
// cx cy cz
|
||||
std::vector<VoxelCube> Voxels[16][16][16];
|
||||
// x y cx cy cz
|
||||
@@ -132,6 +134,15 @@ public:
|
||||
|
||||
return LocalEntityId_t(-1);
|
||||
}
|
||||
|
||||
void load(SB_Region *data) {
|
||||
convertRegionVoxelsToChunks(data->Voxels, (std::vector<VoxelCube>*) Voxels);
|
||||
}
|
||||
|
||||
void save(SB_Region *data) {
|
||||
data->Voxels.clear();
|
||||
convertChunkVoxelsToRegion((const std::vector<VoxelCube>*) Voxels, data->Voxels);
|
||||
}
|
||||
};
|
||||
|
||||
class World {
|
||||
@@ -154,8 +165,6 @@ public:
|
||||
void onCEC_RegionsEnter(ContentEventController *cec, const std::vector<Pos::GlobalRegion> &enter);
|
||||
void onCEC_RegionsLost(ContentEventController *cec, const std::vector<Pos::GlobalRegion> &lost);
|
||||
|
||||
Region* forceLoadOrGetRegion(Pos::GlobalRegion pos);
|
||||
|
||||
DefWorldId_t getDefId() const { return DefId; }
|
||||
};
|
||||
|
||||
|
||||
BIN
assets/grass.png
Normal file
BIN
assets/grass.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 10 KiB |
@@ -8,16 +8,67 @@ layout(location = 0) in FragmentObj {
|
||||
|
||||
layout(location = 0) out vec4 Frame;
|
||||
|
||||
uniform layout(set = 0, binding = 0) sampler2DArray MainAtlas;
|
||||
struct InfoSubTexture {
|
||||
uint Flags; // 1 isExist
|
||||
uint PosXY, WidthHeight;
|
||||
|
||||
uint AnimationFrames_AnimationTimePerFrame;
|
||||
};
|
||||
|
||||
uniform layout(set = 0, binding = 0) sampler2D MainAtlas;
|
||||
layout(set = 0, binding = 1) readonly buffer MainAtlasLayoutObj {
|
||||
vec3 Color;
|
||||
uint SubsCount;
|
||||
uint Counter;
|
||||
uint WidthHeight;
|
||||
|
||||
InfoSubTexture SubTextures[];
|
||||
} MainAtlasLayout;
|
||||
|
||||
uniform layout(set = 1, binding = 0) sampler2DArray LightMap;
|
||||
uniform layout(set = 1, binding = 0) sampler2D LightMap;
|
||||
layout(set = 1, binding = 1) readonly buffer LightMapLayoutObj {
|
||||
vec3 Color;
|
||||
} LightMapLayout;
|
||||
|
||||
void main() {
|
||||
Frame = vec4(1);
|
||||
vec4 atlasColor(uint texId, vec2 uv)
|
||||
{
|
||||
uint flags = (texId & 0xffff0000) >> 16;
|
||||
texId &= 0xffff;
|
||||
vec4 color = vec4(uv, 0, 1);
|
||||
|
||||
if((flags & (2 | 4)) > 0)
|
||||
{
|
||||
if((flags & 2) > 0)
|
||||
color = vec4(1, 1, 1, 1);
|
||||
else if((flags & 4) > 0)
|
||||
{
|
||||
color = vec4(1);
|
||||
}
|
||||
|
||||
}
|
||||
else if(texId >= uint(MainAtlasLayout.SubsCount))
|
||||
return vec4(((int(gl_FragCoord.x / 128) + int(gl_FragCoord.y / 128)) % 2 ) * vec3(0, 1, 1), 1);
|
||||
else {
|
||||
InfoSubTexture texInfo = MainAtlasLayout.SubTextures[texId];
|
||||
if(texInfo.Flags == 0)
|
||||
return vec4(((int(gl_FragCoord.x / 128) + int(gl_FragCoord.y / 128)) % 2 ) * vec3(1, 0, 1), 1);
|
||||
|
||||
uint posX = texInfo.PosXY & 0xffff;
|
||||
uint posY = (texInfo.PosXY >> 16) & 0xffff;
|
||||
uint width = texInfo.WidthHeight & 0xffff;
|
||||
uint height = (texInfo.WidthHeight >> 16) & 0xffff;
|
||||
uint awidth = MainAtlasLayout.WidthHeight & 0xffff;
|
||||
uint aheight = (MainAtlasLayout.WidthHeight >> 16) & 0xffff;
|
||||
|
||||
if((flags & 1) > 0)
|
||||
color = texture(MainAtlas, vec2((posX+0.5f+uv.x*(width-1))/awidth, (posY+0.5f+(1-uv.y)*(height-1))/aheight));
|
||||
else
|
||||
color = texture(MainAtlas, vec2((posX+uv.x*width)/awidth, (posY+(1-uv.y)*height)/aheight));
|
||||
}
|
||||
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
void main() {
|
||||
Frame = atlasColor(Fragment.Texture, Fragment.UV);
|
||||
}
|
||||
Binary file not shown.
Reference in New Issue
Block a user