Графические конвейеры для вокселей и нод
This commit is contained in:
@@ -9,6 +9,26 @@
|
|||||||
|
|
||||||
namespace LV::Client {
|
namespace LV::Client {
|
||||||
|
|
||||||
|
struct GlobalTime {
|
||||||
|
uint32_t Seconds : 22, Sub : 10;
|
||||||
|
|
||||||
|
GlobalTime() = default;
|
||||||
|
GlobalTime(double gTime) {
|
||||||
|
Seconds = int(gTime);
|
||||||
|
Sub = (gTime-int(gTime))*1024;
|
||||||
|
}
|
||||||
|
|
||||||
|
GlobalTime& operator=(double gTime) {
|
||||||
|
Seconds = int(gTime);
|
||||||
|
Sub = (gTime-int(gTime))*1024;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
operator double() const {
|
||||||
|
return double(Seconds) + double(Sub)/1024.;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct VoxelCube {
|
struct VoxelCube {
|
||||||
DefVoxelId_c VoxelId;
|
DefVoxelId_c VoxelId;
|
||||||
Pos::Local256 Left, Right;
|
Pos::Local256 Left, Right;
|
||||||
@@ -129,7 +149,7 @@ public:
|
|||||||
|
|
||||||
virtual ~IServerSession();
|
virtual ~IServerSession();
|
||||||
|
|
||||||
virtual void atFreeDrawTime() = 0;
|
virtual void atFreeDrawTime(GlobalTime gTime, float dTime) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -2,13 +2,13 @@
|
|||||||
#include "Client/Abstract.hpp"
|
#include "Client/Abstract.hpp"
|
||||||
#include "Common/Abstract.hpp"
|
#include "Common/Abstract.hpp"
|
||||||
#include "Common/Net.hpp"
|
#include "Common/Net.hpp"
|
||||||
|
#include <GLFW/glfw3.h>
|
||||||
#include <boost/asio/deadline_timer.hpp>
|
#include <boost/asio/deadline_timer.hpp>
|
||||||
#include <boost/asio/this_coro.hpp>
|
#include <boost/asio/this_coro.hpp>
|
||||||
#include <boost/date_time/posix_time/posix_time_duration.hpp>
|
#include <boost/date_time/posix_time/posix_time_duration.hpp>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <Common/Packets.hpp>
|
#include <Common/Packets.hpp>
|
||||||
#include <GLFW/glfw3.h>
|
|
||||||
#include <glm/ext.hpp>
|
#include <glm/ext.hpp>
|
||||||
|
|
||||||
|
|
||||||
@@ -162,17 +162,24 @@ void ServerSession::onCursorPosChange(int32_t width, int32_t height) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ServerSession::onCursorMove(float xMove, float yMove) {
|
void ServerSession::onCursorMove(float xMove, float yMove) {
|
||||||
|
glm::vec3 deltaPYR;
|
||||||
|
|
||||||
|
static constexpr float PI = glm::pi<float>(), PI2 = PI*2, PI_HALF = PI/2, PI_DEG = PI/180;
|
||||||
|
|
||||||
|
deltaPYR.x = std::clamp(PYR.x + yMove*PI_DEG, -PI_HALF+PI_DEG, PI_HALF-PI_DEG)-PYR.x;
|
||||||
|
deltaPYR.y = std::fmod(PYR.y + xMove*PI_DEG, PI2)-PYR.y;
|
||||||
|
deltaPYR.z = 0;
|
||||||
|
|
||||||
|
double gTime = GTime;
|
||||||
|
float deltaTime = 1-std::min<float>(gTime-PYR_At, 1/PYR_TIME_DELTA)*PYR_TIME_DELTA;
|
||||||
|
PYR_At = GTime;
|
||||||
|
|
||||||
|
PYR += deltaPYR;
|
||||||
|
PYR_Offset = deltaPYR+deltaTime*PYR_Offset;
|
||||||
|
|
||||||
glm::vec3 front = Camera.Quat*glm::vec3(0.0f, 0.0f, -1.0f);
|
glm::vec3 front = Camera.Quat*glm::vec3(0.0f, 0.0f, -1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServerSession::onFrameRendering() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void ServerSession::onFrameRenderEnd() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void ServerSession::onCursorBtn(ISurfaceEventListener::EnumCursorBtn btn, bool state) {
|
void ServerSession::onCursorBtn(ISurfaceEventListener::EnumCursorBtn btn, bool state) {
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -187,8 +194,8 @@ void ServerSession::onJoystick() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServerSession::atFreeDrawTime() {
|
void ServerSession::atFreeDrawTime(GlobalTime gTime, float dTime) {
|
||||||
|
GTime = gTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
coro<> ServerSession::run() {
|
coro<> ServerSession::run() {
|
||||||
|
|||||||
@@ -37,6 +37,12 @@ class ServerSession : public AsyncObject, public IServerSession, public ISurface
|
|||||||
|
|
||||||
boost::lockfree::spsc_queue<std::unique_ptr<ParsedPacket>> NetInputPackets;
|
boost::lockfree::spsc_queue<std::unique_ptr<ParsedPacket>> NetInputPackets;
|
||||||
|
|
||||||
|
//
|
||||||
|
glm::vec3 PYR = glm::vec3(0), PYR_Offset = glm::vec3(0);
|
||||||
|
double PYR_At = 0;
|
||||||
|
static constexpr float PYR_TIME_DELTA = 30;
|
||||||
|
GlobalTime GTime;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Нужен сокет, на котором только что был согласован игровой протокол (asyncInitGameProtocol)
|
// Нужен сокет, на котором только что был согласован игровой протокол (asyncInitGameProtocol)
|
||||||
ServerSession(asio::io_context &ioc, std::unique_ptr<Net::AsyncSocket> &&socket, IRenderSession *rs = nullptr)
|
ServerSession(asio::io_context &ioc, std::unique_ptr<Net::AsyncSocket> &&socket, IRenderSession *rs = nullptr)
|
||||||
@@ -70,14 +76,12 @@ public:
|
|||||||
virtual void onChangeFocusState(bool isFocused) override;
|
virtual void onChangeFocusState(bool isFocused) override;
|
||||||
virtual void onCursorPosChange(int32_t width, int32_t height) override;
|
virtual void onCursorPosChange(int32_t width, int32_t height) override;
|
||||||
virtual void onCursorMove(float xMove, float yMove) override;
|
virtual void onCursorMove(float xMove, float yMove) override;
|
||||||
virtual void onFrameRendering() override;
|
|
||||||
virtual void onFrameRenderEnd() override;
|
|
||||||
|
|
||||||
virtual void onCursorBtn(EnumCursorBtn btn, bool state) override;
|
virtual void onCursorBtn(EnumCursorBtn btn, bool state) override;
|
||||||
virtual void onKeyboardBtn(int btn, int state) override;
|
virtual void onKeyboardBtn(int btn, int state) override;
|
||||||
virtual void onJoystick() override;
|
virtual void onJoystick() override;
|
||||||
|
|
||||||
virtual void atFreeDrawTime() override;
|
virtual void atFreeDrawTime(GlobalTime gTime, float dTime) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
coro<> run();
|
coro<> run();
|
||||||
|
|||||||
@@ -87,17 +87,6 @@ Vulkan::Vulkan(asio::io_context &ioc)
|
|||||||
auto useLock = Game.UseLock.lock();
|
auto useLock = Game.UseLock.lock();
|
||||||
run();
|
run();
|
||||||
GuardLock.reset();
|
GuardLock.reset();
|
||||||
|
|
||||||
if(Game.Session) {
|
|
||||||
Game.Session->shutdown(EnumDisconnect::ByInterface);
|
|
||||||
Game.Session = nullptr;
|
|
||||||
Game.RSession = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(Game.Server) {
|
|
||||||
Game.Server->GS.shutdown("Завершение работы из-за остановки клиента");
|
|
||||||
Game.Server = nullptr;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,8 +121,14 @@ void Vulkan::run()
|
|||||||
assert(!vkCreateSemaphore(Graphics.Device, &semaphoreCreateInfo, NULL, &SemaphoreDrawComplete));
|
assert(!vkCreateSemaphore(Graphics.Device, &semaphoreCreateInfo, NULL, &SemaphoreDrawComplete));
|
||||||
|
|
||||||
|
|
||||||
while(!NeedShutdown)
|
double prevTime = glfwGetTime();
|
||||||
|
while(!NeedShutdown
|
||||||
|
|| (Game.Session && Game.Session->isConnected())
|
||||||
|
|| (Game.Server && Game.Server->GS.isAlive()))
|
||||||
{
|
{
|
||||||
|
float dTime = glfwGetTime()-prevTime;
|
||||||
|
prevTime = glfwGetTime();
|
||||||
|
|
||||||
Screen.State = DrawState::Begin;
|
Screen.State = DrawState::Begin;
|
||||||
{
|
{
|
||||||
std::lock_guard lock(Screen.BeforeDrawMtx);
|
std::lock_guard lock(Screen.BeforeDrawMtx);
|
||||||
@@ -144,8 +139,16 @@ void Vulkan::run()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(glfwWindowShouldClose(Graphics.Window)) {
|
if(!NeedShutdown && glfwWindowShouldClose(Graphics.Window)) {
|
||||||
NeedShutdown = true;
|
NeedShutdown = true;
|
||||||
|
|
||||||
|
if(Game.Session) {
|
||||||
|
Game.Session->shutdown(EnumDisconnect::ByInterface);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(Game.Server) {
|
||||||
|
Game.Server->GS.shutdown("Завершение работы из-за остановки клиента");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(Game.Session) {
|
if(Game.Session) {
|
||||||
@@ -168,6 +171,10 @@ void Vulkan::run()
|
|||||||
// if(CallBeforeDraw)
|
// if(CallBeforeDraw)
|
||||||
// CallBeforeDraw(this);
|
// CallBeforeDraw(this);
|
||||||
|
|
||||||
|
if(Game.RSession) {
|
||||||
|
Game.RSession->beforeDraw();
|
||||||
|
}
|
||||||
|
|
||||||
glfwPollEvents();
|
glfwPollEvents();
|
||||||
|
|
||||||
VkResult err;
|
VkResult err;
|
||||||
@@ -251,8 +258,17 @@ void Vulkan::run()
|
|||||||
vkCmdSetScissor(Graphics.CommandBufferRender, 0, 1, &scissor);
|
vkCmdSetScissor(Graphics.CommandBufferRender, 0, 1, &scissor);
|
||||||
}
|
}
|
||||||
|
|
||||||
// if(CallOnDraw)
|
GlobalTime gTime = glfwGetTime();
|
||||||
// CallOnDraw(this, 0, Graphics.CommandBufferRender);
|
|
||||||
|
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);
|
vkCmdEndRenderPass(Graphics.CommandBufferRender);
|
||||||
|
|
||||||
@@ -400,6 +416,10 @@ void Vulkan::run()
|
|||||||
assert(!err);
|
assert(!err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(Game.Session) {
|
||||||
|
Game.Session->atFreeDrawTime(gTime, dTime);
|
||||||
|
}
|
||||||
|
|
||||||
assert(!vkQueueWaitIdle(Graphics.DeviceQueueGraphic));
|
assert(!vkQueueWaitIdle(Graphics.DeviceQueueGraphic));
|
||||||
|
|
||||||
vkDeviceWaitIdle(Graphics.Device);
|
vkDeviceWaitIdle(Graphics.Device);
|
||||||
@@ -410,6 +430,10 @@ void Vulkan::run()
|
|||||||
vkDestroySemaphore(Graphics.Device, SemaphoreDrawComplete, nullptr);
|
vkDestroySemaphore(Graphics.Device, SemaphoreDrawComplete, nullptr);
|
||||||
|
|
||||||
Graphics.ThisThread = std::thread::id();
|
Graphics.ThisThread = std::thread::id();
|
||||||
|
|
||||||
|
Game.Session = nullptr;
|
||||||
|
Game.RSession = nullptr;
|
||||||
|
Game.Server = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Vulkan::glfwCallbackError(int error, const char *description)
|
void Vulkan::glfwCallbackError(int error, const char *description)
|
||||||
@@ -1308,7 +1332,7 @@ void Vulkan::initNextSettings()
|
|||||||
} else {
|
} else {
|
||||||
for(const std::shared_ptr<IVulkanDependent> &dependent : ROS_Dependents)
|
for(const std::shared_ptr<IVulkanDependent> &dependent : ROS_Dependents)
|
||||||
{
|
{
|
||||||
if(dependent->needRebuild() != EnumRebuildType::None || dynamic_cast<Pipeline*>(dependent.get()))
|
if(/*dependent->needRebuild() != EnumRebuildType::None || */ dynamic_cast<Pipeline*>(dependent.get()))
|
||||||
dependent->free(this);
|
dependent->free(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1842,6 +1866,7 @@ bool Vulkan::needFullVulkanRebuild()
|
|||||||
std::shared_ptr<ShaderModule> Vulkan::createShader(const ByteBuffer &data)
|
std::shared_ptr<ShaderModule> Vulkan::createShader(const ByteBuffer &data)
|
||||||
{
|
{
|
||||||
assert(Graphics.Device);
|
assert(Graphics.Device);
|
||||||
|
assert(data.size());
|
||||||
std::shared_ptr<ShaderModule> module = std::make_shared<ShaderModule>(data);
|
std::shared_ptr<ShaderModule> module = std::make_shared<ShaderModule>(data);
|
||||||
std::dynamic_pointer_cast<IVulkanDependent>(module)->init(this);
|
std::dynamic_pointer_cast<IVulkanDependent>(module)->init(this);
|
||||||
ROS_Dependents.insert(module);
|
ROS_Dependents.insert(module);
|
||||||
@@ -1967,7 +1992,8 @@ void Vulkan::gui_MainMenu() {
|
|||||||
|
|
||||||
if(ConnectionProgress.Socket) {
|
if(ConnectionProgress.Socket) {
|
||||||
std::unique_ptr<Net::AsyncSocket> sock = std::move(ConnectionProgress.Socket);
|
std::unique_ptr<Net::AsyncSocket> sock = std::move(ConnectionProgress.Socket);
|
||||||
Game.RSession = std::make_unique<VulkanRenderSession>(this);
|
Game.RSession = std::make_unique<VulkanRenderSession>();
|
||||||
|
*this << Game.RSession;
|
||||||
Game.Session = std::make_unique<ServerSession>(IOC, std::move(sock), Game.RSession.get());
|
Game.Session = std::make_unique<ServerSession>(IOC, std::move(sock), Game.RSession.get());
|
||||||
Game.RSession->setServerSession(Game.Session.get());
|
Game.RSession->setServerSession(Game.Session.get());
|
||||||
Game.ImGuiInterfaces.push_back(&Vulkan::gui_ConnectedToServer);
|
Game.ImGuiInterfaces.push_back(&Vulkan::gui_ConnectedToServer);
|
||||||
@@ -1989,19 +2015,18 @@ void Vulkan::gui_ConnectedToServer() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
EnumRebuildType IVulkanDependent::needRebuild() { return EnumRebuildType::None; }
|
|
||||||
IVulkanDependent::~IVulkanDependent() = default;
|
IVulkanDependent::~IVulkanDependent() = default;
|
||||||
|
|
||||||
void Vulkan::updateResources()
|
void Vulkan::updateResources()
|
||||||
{
|
{
|
||||||
for(const std::shared_ptr<IVulkanDependent> &dependent : ROS_Dependents)
|
// for(const std::shared_ptr<IVulkanDependent> &dependent : ROS_Dependents)
|
||||||
{
|
// {
|
||||||
if(dependent->needRebuild() != EnumRebuildType::None)
|
// if(dependent->needRebuild() != EnumRebuildType::None)
|
||||||
{
|
// {
|
||||||
dependent->free(this);
|
// dependent->free(this);
|
||||||
dependent->init(this);
|
// dependent->init(this);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -2412,11 +2437,6 @@ void Pipeline::init(Vulkan *instance)
|
|||||||
assert(!vkCreateGraphicsPipelines(instance->Graphics.Device, VK_NULL_HANDLE, 1, &pipeline, nullptr, &PipelineObj));
|
assert(!vkCreateGraphicsPipelines(instance->Graphics.Device, VK_NULL_HANDLE, 1, &pipeline, nullptr, &PipelineObj));
|
||||||
}
|
}
|
||||||
|
|
||||||
EnumRebuildType Pipeline::needRebuild()
|
|
||||||
{
|
|
||||||
return PipelineObj ? EnumRebuildType::None : EnumRebuildType::Urgently;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Shader
|
// Shader
|
||||||
|
|
||||||
@@ -4418,4 +4438,115 @@ FontAtlas::GlyphInfo FontAtlas::getGlyph(UChar wc, uint16_t size)
|
|||||||
return CharToInfo[glyphId] = info;
|
return CharToInfo[glyphId] = info;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
PipelineVF::PipelineVF(std::shared_ptr<DescriptorLayout> layout, const std::string &vertex,
|
||||||
|
const std::string &fragment)
|
||||||
|
: Pipeline(layout), PathVertex(vertex), PathFragment(fragment)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
PipelineVF::~PipelineVF() = default;
|
||||||
|
|
||||||
|
void PipelineVF::init(Vulkan *instance)
|
||||||
|
{
|
||||||
|
if(!ShaderVertex)
|
||||||
|
ShaderVertex = instance->createShaderFromFile(PathVertex);
|
||||||
|
|
||||||
|
if(!ShaderFragment)
|
||||||
|
ShaderFragment = instance->createShaderFromFile(PathFragment);
|
||||||
|
|
||||||
|
Settings.ShaderStages =
|
||||||
|
{
|
||||||
|
{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
|
||||||
|
.pNext = nullptr,
|
||||||
|
.flags = 0,
|
||||||
|
.stage = VK_SHADER_STAGE_VERTEX_BIT,
|
||||||
|
.module = *ShaderVertex,
|
||||||
|
.pName = "main",
|
||||||
|
.pSpecializationInfo = nullptr
|
||||||
|
}, {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
|
||||||
|
.pNext = nullptr,
|
||||||
|
.flags = 0,
|
||||||
|
.stage = VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||||
|
.module = *ShaderFragment,
|
||||||
|
.pName = "main",
|
||||||
|
.pSpecializationInfo = nullptr
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Pipeline::init(instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
PipelineVGF::PipelineVGF(std::shared_ptr<DescriptorLayout> layout, const std::string &vertex,
|
||||||
|
const std::string &geometry, const std::string &fragment)
|
||||||
|
: Pipeline(layout), PathVertex(vertex), PathGeometry(geometry), PathFragment(fragment)
|
||||||
|
{
|
||||||
|
// Settings.ShaderVertexBindings =
|
||||||
|
// {
|
||||||
|
// {
|
||||||
|
// .binding = 0,
|
||||||
|
// .stride = sizeof(Client::Chunk::Vertex),
|
||||||
|
// .inputRate = VK_VERTEX_INPUT_RATE_VERTEX
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
|
// Settings.ShaderVertexAttribute =
|
||||||
|
// {
|
||||||
|
// {
|
||||||
|
// .location = 0,
|
||||||
|
// .binding = 0,
|
||||||
|
// .format = VK_FORMAT_R32_UINT,
|
||||||
|
// .offset = 0
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
}
|
||||||
|
|
||||||
|
PipelineVGF::~PipelineVGF() = default;
|
||||||
|
|
||||||
|
void PipelineVGF::init(Vulkan *instance)
|
||||||
|
{
|
||||||
|
if(!ShaderVertex)
|
||||||
|
ShaderVertex = instance->createShaderFromFile(PathVertex);
|
||||||
|
|
||||||
|
if(!ShaderGeometry)
|
||||||
|
ShaderGeometry = instance->createShaderFromFile(PathGeometry);
|
||||||
|
|
||||||
|
if(!ShaderFragment)
|
||||||
|
ShaderFragment = instance->createShaderFromFile(PathFragment);
|
||||||
|
|
||||||
|
Settings.ShaderStages =
|
||||||
|
{
|
||||||
|
{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
|
||||||
|
.pNext = nullptr,
|
||||||
|
.flags = 0,
|
||||||
|
.stage = VK_SHADER_STAGE_VERTEX_BIT,
|
||||||
|
.module = *ShaderVertex,
|
||||||
|
.pName = "main",
|
||||||
|
.pSpecializationInfo = nullptr
|
||||||
|
}, {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
|
||||||
|
.pNext = nullptr,
|
||||||
|
.flags = 0,
|
||||||
|
.stage = VK_SHADER_STAGE_GEOMETRY_BIT,
|
||||||
|
.module = *ShaderGeometry,
|
||||||
|
.pName = "main",
|
||||||
|
.pSpecializationInfo = nullptr
|
||||||
|
}, {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
|
||||||
|
.pNext = nullptr,
|
||||||
|
.flags = 0,
|
||||||
|
.stage = VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||||
|
.module = *ShaderFragment,
|
||||||
|
.pName = "main",
|
||||||
|
.pSpecializationInfo = nullptr
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Pipeline::init(instance);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -238,7 +238,7 @@ public:
|
|||||||
struct {
|
struct {
|
||||||
DestroyLock UseLock;
|
DestroyLock UseLock;
|
||||||
std::thread MainThread;
|
std::thread MainThread;
|
||||||
std::unique_ptr<VulkanRenderSession> RSession;
|
std::shared_ptr<VulkanRenderSession> RSession;
|
||||||
std::unique_ptr<ServerSession> Session;
|
std::unique_ptr<ServerSession> Session;
|
||||||
|
|
||||||
std::list<void (Vulkan::*)()> ImGuiInterfaces;
|
std::list<void (Vulkan::*)()> ImGuiInterfaces;
|
||||||
@@ -358,17 +358,10 @@ public:
|
|||||||
void gui_ConnectedToServer();
|
void gui_ConnectedToServer();
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class EnumRebuildType {
|
|
||||||
None,
|
|
||||||
Need,
|
|
||||||
Urgently
|
|
||||||
};
|
|
||||||
|
|
||||||
class IVulkanDependent : public std::enable_shared_from_this<IVulkanDependent> {
|
class IVulkanDependent : public std::enable_shared_from_this<IVulkanDependent> {
|
||||||
protected:
|
protected:
|
||||||
virtual void free(Vulkan *instance) = 0;
|
virtual void free(Vulkan *instance) = 0;
|
||||||
virtual void init(Vulkan *instance) = 0;
|
virtual void init(Vulkan *instance) = 0;
|
||||||
virtual EnumRebuildType needRebuild();
|
|
||||||
|
|
||||||
friend Vulkan;
|
friend Vulkan;
|
||||||
friend Pipeline;
|
friend Pipeline;
|
||||||
@@ -449,8 +442,6 @@ protected:
|
|||||||
|
|
||||||
virtual void free(Vulkan *instance) override;
|
virtual void free(Vulkan *instance) override;
|
||||||
virtual void init(Vulkan *instance) override;
|
virtual void init(Vulkan *instance) override;
|
||||||
// Если необходимо изменить графический конвейер, будет вызвано free и init
|
|
||||||
virtual EnumRebuildType needRebuild() override;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Pipeline(std::shared_ptr<DescriptorLayout> layout);
|
Pipeline(std::shared_ptr<DescriptorLayout> layout);
|
||||||
@@ -1000,5 +991,29 @@ public:
|
|||||||
size_t getLastUpdate() { return LastUpdate; }
|
size_t getLastUpdate() { return LastUpdate; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class PipelineVF : public Pipeline {
|
||||||
|
std::string PathVertex, PathFragment;
|
||||||
|
std::shared_ptr<ShaderModule> ShaderVertex, ShaderFragment;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void init(Vulkan *instance) override;
|
||||||
|
|
||||||
|
public:
|
||||||
|
PipelineVF(std::shared_ptr<DescriptorLayout> layout, const std::string &vertex, const std::string &fragment);
|
||||||
|
virtual ~PipelineVF();
|
||||||
|
};
|
||||||
|
|
||||||
|
class PipelineVGF : public Pipeline {
|
||||||
|
std::string PathVertex, PathGeometry, PathFragment;
|
||||||
|
std::shared_ptr<ShaderModule> ShaderVertex, ShaderGeometry, ShaderFragment;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void init(Vulkan *instance) override;
|
||||||
|
|
||||||
|
public:
|
||||||
|
PipelineVGF(std::shared_ptr<DescriptorLayout> layout, const std::string &vertex, const std::string &geometry, const std::string &fragment);
|
||||||
|
virtual ~PipelineVGF();
|
||||||
|
};
|
||||||
|
|
||||||
} /* namespace TOS::Navie::VK */
|
} /* namespace TOS::Navie::VK */
|
||||||
|
|
||||||
|
|||||||
@@ -1,19 +1,464 @@
|
|||||||
#include "VulkanRenderSession.hpp"
|
#include "VulkanRenderSession.hpp"
|
||||||
|
#include <vulkan/vulkan_core.h>
|
||||||
|
|
||||||
namespace LV::Client::VK {
|
namespace LV::Client::VK {
|
||||||
|
|
||||||
|
|
||||||
VulkanRenderSession::VulkanRenderSession(VK::Vulkan *vkInst)
|
VulkanRenderSession::VulkanRenderSession()
|
||||||
: VkInst(vkInst),
|
|
||||||
MainAtlas(vkInst)
|
|
||||||
{
|
{
|
||||||
assert(VkInst);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VulkanRenderSession::~VulkanRenderSession() {
|
VulkanRenderSession::~VulkanRenderSession() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VulkanRenderSession::free(Vulkan *instance) {
|
||||||
|
if(instance && instance->Graphics.Device)
|
||||||
|
{
|
||||||
|
if(VoxelOpaquePipeline)
|
||||||
|
vkDestroyPipeline(instance->Graphics.Device, VoxelOpaquePipeline, nullptr);
|
||||||
|
if(VoxelTransparentPipeline)
|
||||||
|
vkDestroyPipeline(instance->Graphics.Device, VoxelTransparentPipeline, nullptr);
|
||||||
|
if(NodeStaticOpaquePipeline)
|
||||||
|
vkDestroyPipeline(instance->Graphics.Device, NodeStaticOpaquePipeline, nullptr);
|
||||||
|
if(NodeStaticTransparentPipeline)
|
||||||
|
vkDestroyPipeline(instance->Graphics.Device, NodeStaticTransparentPipeline, nullptr);
|
||||||
|
|
||||||
|
if(MainAtlas_LightMap_PipelineLayout)
|
||||||
|
vkDestroyPipelineLayout(instance->Graphics.Device, MainAtlas_LightMap_PipelineLayout, nullptr);
|
||||||
|
|
||||||
|
if(MainAtlasDescLayout)
|
||||||
|
vkDestroyDescriptorSetLayout(instance->Graphics.Device, MainAtlasDescLayout, nullptr);
|
||||||
|
if(LightMapDescLayout)
|
||||||
|
vkDestroyDescriptorSetLayout(instance->Graphics.Device, LightMapDescLayout, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
VoxelOpaquePipeline = VK_NULL_HANDLE;
|
||||||
|
VoxelTransparentPipeline = VK_NULL_HANDLE;
|
||||||
|
NodeStaticOpaquePipeline = VK_NULL_HANDLE;
|
||||||
|
NodeStaticTransparentPipeline = VK_NULL_HANDLE;
|
||||||
|
|
||||||
|
MainAtlas_LightMap_PipelineLayout = VK_NULL_HANDLE;
|
||||||
|
|
||||||
|
MainAtlasDescLayout = VK_NULL_HANDLE;
|
||||||
|
LightMapDescLayout = VK_NULL_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VulkanRenderSession::init(Vulkan *instance) {
|
||||||
|
if(VkInst != instance) {
|
||||||
|
VkInst = instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Разметка дескрипторов
|
||||||
|
if(!MainAtlasDescLayout) {
|
||||||
|
std::vector<VkDescriptorSetLayoutBinding> shaderLayoutBindings =
|
||||||
|
{
|
||||||
|
{
|
||||||
|
.binding = 0,
|
||||||
|
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
||||||
|
.descriptorCount = 1,
|
||||||
|
.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||||
|
.pImmutableSamplers = nullptr
|
||||||
|
}, {
|
||||||
|
.binding = 1,
|
||||||
|
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||||
|
.descriptorCount = 1,
|
||||||
|
.stageFlags = VK_SHADER_STAGE_VERTEX_BIT,
|
||||||
|
.pImmutableSamplers = nullptr
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const VkDescriptorSetLayoutCreateInfo descriptorLayout =
|
||||||
|
{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
|
||||||
|
.pNext = nullptr,
|
||||||
|
.flags = 0,
|
||||||
|
.bindingCount = (uint32_t) shaderLayoutBindings.size(),
|
||||||
|
.pBindings = shaderLayoutBindings.data()
|
||||||
|
};
|
||||||
|
|
||||||
|
assert(!vkCreateDescriptorSetLayout(
|
||||||
|
instance->Graphics.Device, &descriptorLayout, nullptr, &MainAtlasDescLayout));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!LightMapDescLayout) {
|
||||||
|
std::vector<VkDescriptorSetLayoutBinding> shaderLayoutBindings =
|
||||||
|
{
|
||||||
|
{
|
||||||
|
.binding = 0,
|
||||||
|
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
||||||
|
.descriptorCount = 1,
|
||||||
|
.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||||
|
.pImmutableSamplers = nullptr
|
||||||
|
}, {
|
||||||
|
.binding = 1,
|
||||||
|
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||||
|
.descriptorCount = 1,
|
||||||
|
.stageFlags = VK_SHADER_STAGE_VERTEX_BIT,
|
||||||
|
.pImmutableSamplers = nullptr
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const VkDescriptorSetLayoutCreateInfo descriptorLayout =
|
||||||
|
{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
|
||||||
|
.pNext = nullptr,
|
||||||
|
.flags = 0,
|
||||||
|
.bindingCount = (uint32_t) shaderLayoutBindings.size(),
|
||||||
|
.pBindings = shaderLayoutBindings.data()
|
||||||
|
};
|
||||||
|
|
||||||
|
assert(!vkCreateDescriptorSetLayout( instance->Graphics.Device, &descriptorLayout, nullptr, &LightMapDescLayout));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<VkPushConstantRange> worldWideShaderPushConstants =
|
||||||
|
{
|
||||||
|
{
|
||||||
|
.stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_GEOMETRY_BIT,
|
||||||
|
.offset = 0,
|
||||||
|
.size = uint32_t(sizeof(WorldPCO))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Разметка графических конвейеров
|
||||||
|
if(!MainAtlas_LightMap_PipelineLayout) {
|
||||||
|
std::vector<VkDescriptorSetLayout> layouts =
|
||||||
|
{
|
||||||
|
MainAtlasDescLayout,
|
||||||
|
LightMapDescLayout
|
||||||
|
};
|
||||||
|
|
||||||
|
const VkPipelineLayoutCreateInfo pPipelineLayoutCreateInfo =
|
||||||
|
{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
|
||||||
|
.pNext = nullptr,
|
||||||
|
.flags = 0,
|
||||||
|
.setLayoutCount = (uint32_t) layouts.size(),
|
||||||
|
.pSetLayouts = layouts.data(),
|
||||||
|
.pushConstantRangeCount = (uint32_t) worldWideShaderPushConstants.size(),
|
||||||
|
.pPushConstantRanges = worldWideShaderPushConstants.data()
|
||||||
|
};
|
||||||
|
|
||||||
|
assert(!vkCreatePipelineLayout(instance->Graphics.Device, &pPipelineLayoutCreateInfo, nullptr, &MainAtlas_LightMap_PipelineLayout));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Настройка мультисемплинга
|
||||||
|
// Может нужно будет в будущем связать с настройками главного буфера
|
||||||
|
VkPipelineMultisampleStateCreateInfo multisample =
|
||||||
|
{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
|
||||||
|
.pNext = nullptr,
|
||||||
|
.flags = 0,
|
||||||
|
.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT,
|
||||||
|
.sampleShadingEnable = false,
|
||||||
|
.minSampleShading = 0.0f,
|
||||||
|
.pSampleMask = nullptr,
|
||||||
|
.alphaToCoverageEnable = false,
|
||||||
|
.alphaToOneEnable = false
|
||||||
|
};
|
||||||
|
|
||||||
|
VkPipelineCacheCreateInfo infoPipelineCache;
|
||||||
|
memset(&infoPipelineCache, 0, sizeof(infoPipelineCache));
|
||||||
|
infoPipelineCache.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
|
||||||
|
|
||||||
|
// Конвейеры для вокселей
|
||||||
|
if(!VoxelOpaquePipeline || !VoxelTransparentPipeline
|
||||||
|
|| !NodeStaticOpaquePipeline || !NodeStaticTransparentPipeline)
|
||||||
|
{
|
||||||
|
// Для статичных непрозрачных и полупрозрачных вокселей
|
||||||
|
if(!VoxelShaderVertex)
|
||||||
|
VoxelShaderVertex = VkInst->createShaderFromFile("assets/shaders/chunk/voxel.vert.bin");
|
||||||
|
|
||||||
|
if(!VoxelShaderGeometry)
|
||||||
|
VoxelShaderGeometry = VkInst->createShaderFromFile("assets/shaders/chunk/voxel.geom.bin");
|
||||||
|
|
||||||
|
if(!VoxelShaderFragmentOpaque)
|
||||||
|
VoxelShaderFragmentOpaque = VkInst->createShaderFromFile("assets/shaders/chunk/voxel_opaque.frag.bin");
|
||||||
|
|
||||||
|
if(!VoxelShaderFragmentTransparent)
|
||||||
|
VoxelShaderFragmentTransparent = VkInst->createShaderFromFile("assets/shaders/chunk/voxel_transparent.frag.bin");
|
||||||
|
|
||||||
|
// Конвейер шейдеров
|
||||||
|
std::vector<VkPipelineShaderStageCreateInfo> shaderStages =
|
||||||
|
{
|
||||||
|
{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
|
||||||
|
.pNext = nullptr,
|
||||||
|
.flags = 0,
|
||||||
|
.stage = VK_SHADER_STAGE_VERTEX_BIT,
|
||||||
|
.module = *VoxelShaderVertex,
|
||||||
|
.pName = "main",
|
||||||
|
.pSpecializationInfo = nullptr
|
||||||
|
}, {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
|
||||||
|
.pNext = nullptr,
|
||||||
|
.flags = 0,
|
||||||
|
.stage = VK_SHADER_STAGE_GEOMETRY_BIT,
|
||||||
|
.module = *VoxelShaderGeometry,
|
||||||
|
.pName = "main",
|
||||||
|
.pSpecializationInfo = nullptr
|
||||||
|
}, {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
|
||||||
|
.pNext = nullptr,
|
||||||
|
.flags = 0,
|
||||||
|
.stage = VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||||
|
.module = *VoxelShaderFragmentOpaque,
|
||||||
|
.pName = "main",
|
||||||
|
.pSpecializationInfo = nullptr
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Вершины шейдера
|
||||||
|
// Настройка формата вершин шейдера
|
||||||
|
std::vector<VkVertexInputBindingDescription> shaderVertexBindings =
|
||||||
|
{
|
||||||
|
{
|
||||||
|
.binding = 0,
|
||||||
|
.stride = sizeof(VoxelVertexPoint),
|
||||||
|
.inputRate = VK_VERTEX_INPUT_RATE_VERTEX
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<VkVertexInputAttributeDescription> shaderVertexAttribute =
|
||||||
|
{
|
||||||
|
{
|
||||||
|
.location = 0,
|
||||||
|
.binding = 0,
|
||||||
|
.format = VK_FORMAT_R32G32B32_UINT,
|
||||||
|
.offset = 0
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
VkPipelineVertexInputStateCreateInfo createInfoVertexInput =
|
||||||
|
{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
|
||||||
|
.pNext = nullptr,
|
||||||
|
.flags = 0,
|
||||||
|
.vertexBindingDescriptionCount = (uint32_t) shaderVertexBindings.size(),
|
||||||
|
.pVertexBindingDescriptions = shaderVertexBindings.data(),
|
||||||
|
.vertexAttributeDescriptionCount = (uint32_t) shaderVertexAttribute.size(),
|
||||||
|
.pVertexAttributeDescriptions = shaderVertexAttribute.data()
|
||||||
|
};
|
||||||
|
|
||||||
|
// Топология вершин на входе (треугольники, линии, точки)
|
||||||
|
VkPipelineInputAssemblyStateCreateInfo ia =
|
||||||
|
{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
|
||||||
|
.pNext = nullptr,
|
||||||
|
.flags = 0,
|
||||||
|
.topology = VK_PRIMITIVE_TOPOLOGY_POINT_LIST,
|
||||||
|
.primitiveRestartEnable = false
|
||||||
|
};
|
||||||
|
|
||||||
|
VkPipelineViewportStateCreateInfo vp =
|
||||||
|
{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
|
||||||
|
.pNext = nullptr,
|
||||||
|
.flags = 0,
|
||||||
|
.viewportCount = 1,
|
||||||
|
.pViewports = nullptr,
|
||||||
|
.scissorCount = 1,
|
||||||
|
.pScissors = nullptr
|
||||||
|
};
|
||||||
|
|
||||||
|
// Настройки растеризатора
|
||||||
|
VkPipelineRasterizationStateCreateInfo rasterization =
|
||||||
|
{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
|
||||||
|
.pNext = nullptr,
|
||||||
|
.flags = 0,
|
||||||
|
.depthClampEnable = false,
|
||||||
|
.rasterizerDiscardEnable = false,
|
||||||
|
.polygonMode = VK_POLYGON_MODE_FILL,
|
||||||
|
.cullMode = VK_CULL_MODE_BACK_BIT,
|
||||||
|
.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE,
|
||||||
|
.depthBiasEnable = false,
|
||||||
|
.depthBiasConstantFactor = 0.0f,
|
||||||
|
.depthBiasClamp = 0.0f,
|
||||||
|
.depthBiasSlopeFactor = 0.0f,
|
||||||
|
.lineWidth = 1.0f
|
||||||
|
};
|
||||||
|
|
||||||
|
// Тест буфера глубины и трафарета
|
||||||
|
VkPipelineDepthStencilStateCreateInfo depthStencil =
|
||||||
|
{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
|
||||||
|
.pNext = nullptr,
|
||||||
|
.flags = 0,
|
||||||
|
.depthTestEnable = true,
|
||||||
|
.depthWriteEnable = true,
|
||||||
|
.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL,
|
||||||
|
.depthBoundsTestEnable = false,
|
||||||
|
.stencilTestEnable = false,
|
||||||
|
.front = VkStencilOpState
|
||||||
|
{
|
||||||
|
.failOp = VK_STENCIL_OP_KEEP,
|
||||||
|
.passOp = VK_STENCIL_OP_KEEP,
|
||||||
|
.depthFailOp = VK_STENCIL_OP_KEEP,
|
||||||
|
.compareOp = VK_COMPARE_OP_ALWAYS,
|
||||||
|
.compareMask = 0x0,
|
||||||
|
.writeMask = 0x0,
|
||||||
|
.reference = 0x0
|
||||||
|
},
|
||||||
|
.back = VkStencilOpState
|
||||||
|
{
|
||||||
|
.failOp = VK_STENCIL_OP_KEEP,
|
||||||
|
.passOp = VK_STENCIL_OP_KEEP,
|
||||||
|
.depthFailOp = VK_STENCIL_OP_KEEP,
|
||||||
|
.compareOp = VK_COMPARE_OP_ALWAYS,
|
||||||
|
.compareMask = 0x0,
|
||||||
|
.writeMask = 0x0,
|
||||||
|
.reference = 0x0
|
||||||
|
},
|
||||||
|
.minDepthBounds = 0.0f,
|
||||||
|
.maxDepthBounds = 0.0f
|
||||||
|
};
|
||||||
|
|
||||||
|
// Логика смешивания цветов
|
||||||
|
std::vector<VkPipelineColorBlendAttachmentState> colorBlend =
|
||||||
|
{
|
||||||
|
{
|
||||||
|
.blendEnable = false,
|
||||||
|
.srcColorBlendFactor = VK_BLEND_FACTOR_ZERO,
|
||||||
|
.dstColorBlendFactor = VK_BLEND_FACTOR_ONE,
|
||||||
|
.colorBlendOp = VK_BLEND_OP_ADD,
|
||||||
|
.srcAlphaBlendFactor = VK_BLEND_FACTOR_ZERO,
|
||||||
|
.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO,
|
||||||
|
.alphaBlendOp = VK_BLEND_OP_ADD,
|
||||||
|
.colorWriteMask = 0xf
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
VkPipelineColorBlendStateCreateInfo cb =
|
||||||
|
{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
|
||||||
|
.pNext = nullptr,
|
||||||
|
.flags = 0,
|
||||||
|
.logicOpEnable = VK_FALSE,
|
||||||
|
.logicOp = VK_LOGIC_OP_CLEAR,
|
||||||
|
.attachmentCount = (uint32_t) colorBlend.size(),
|
||||||
|
.pAttachments = colorBlend.data(),
|
||||||
|
.blendConstants = {0.f, 0.f, 0.f, 0.f}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Настройки конвейера, которые могут быть изменены без пересоздания конвейера
|
||||||
|
std::vector<VkDynamicState> dynamicStates =
|
||||||
|
{
|
||||||
|
VK_DYNAMIC_STATE_VIEWPORT,
|
||||||
|
VK_DYNAMIC_STATE_SCISSOR
|
||||||
|
};
|
||||||
|
|
||||||
|
VkPipelineDynamicStateCreateInfo dynamicState =
|
||||||
|
{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
|
||||||
|
.pNext = nullptr,
|
||||||
|
.flags = 0,
|
||||||
|
.dynamicStateCount = (uint32_t) dynamicStates.size(),
|
||||||
|
.pDynamicStates = dynamicStates.data(),
|
||||||
|
};
|
||||||
|
|
||||||
|
VkGraphicsPipelineCreateInfo pipeline =
|
||||||
|
{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
|
||||||
|
.pNext = nullptr,
|
||||||
|
.flags = 0,
|
||||||
|
.stageCount = (uint32_t) shaderStages.size(),
|
||||||
|
.pStages = shaderStages.data(),
|
||||||
|
.pVertexInputState = &createInfoVertexInput,
|
||||||
|
.pInputAssemblyState = &ia,
|
||||||
|
.pTessellationState = nullptr,
|
||||||
|
.pViewportState = &vp,
|
||||||
|
.pRasterizationState = &rasterization,
|
||||||
|
.pMultisampleState = &multisample,
|
||||||
|
.pDepthStencilState = &depthStencil,
|
||||||
|
.pColorBlendState = &cb,
|
||||||
|
.pDynamicState = &dynamicState,
|
||||||
|
.layout = MainAtlas_LightMap_PipelineLayout,
|
||||||
|
.renderPass = instance->Graphics.RenderPass,
|
||||||
|
.subpass = 0,
|
||||||
|
.basePipelineHandle = nullptr,
|
||||||
|
.basePipelineIndex = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
if(!VoxelOpaquePipeline)
|
||||||
|
assert(!vkCreateGraphicsPipelines(instance->Graphics.Device, VK_NULL_HANDLE, 1, &pipeline, nullptr, &VoxelOpaquePipeline));
|
||||||
|
|
||||||
|
if(!VoxelTransparentPipeline) {
|
||||||
|
shaderStages[2].module = *VoxelShaderFragmentTransparent,
|
||||||
|
|
||||||
|
colorBlend[0] =
|
||||||
|
{
|
||||||
|
.blendEnable = VK_TRUE,
|
||||||
|
.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA,
|
||||||
|
.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
|
||||||
|
.colorBlendOp = VK_BLEND_OP_ADD,
|
||||||
|
.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE,
|
||||||
|
.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO,
|
||||||
|
.alphaBlendOp = VK_BLEND_OP_ADD,
|
||||||
|
.colorWriteMask = 0xf
|
||||||
|
};
|
||||||
|
|
||||||
|
assert(!vkCreateGraphicsPipelines(instance->Graphics.Device, VK_NULL_HANDLE, 1, &pipeline, nullptr, &VoxelTransparentPipeline));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Для статичных непрозрачных и полупрозрачных нод
|
||||||
|
if(!NodeShaderVertex)
|
||||||
|
NodeShaderVertex = VkInst->createShaderFromFile("assets/shaders/chunk/node.vert.bin");
|
||||||
|
|
||||||
|
if(!NodeShaderGeometry)
|
||||||
|
NodeShaderGeometry = VkInst->createShaderFromFile("assets/shaders/chunk/node.geom.bin");
|
||||||
|
|
||||||
|
if(!NodeShaderFragmentOpaque)
|
||||||
|
NodeShaderFragmentOpaque = VkInst->createShaderFromFile("assets/shaders/chunk/node_opaque.frag.bin");
|
||||||
|
|
||||||
|
if(!NodeShaderFragmentTransparent)
|
||||||
|
NodeShaderFragmentTransparent = VkInst->createShaderFromFile("assets/shaders/chunk/node_transparent.frag.bin");
|
||||||
|
|
||||||
|
ia.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
|
||||||
|
|
||||||
|
shaderStages[0].module = *NodeShaderVertex;
|
||||||
|
shaderStages[1].module = *NodeShaderGeometry;
|
||||||
|
shaderStages[2].module = *NodeShaderFragmentOpaque;
|
||||||
|
|
||||||
|
colorBlend[0] =
|
||||||
|
{
|
||||||
|
.blendEnable = false,
|
||||||
|
.srcColorBlendFactor = VK_BLEND_FACTOR_ZERO,
|
||||||
|
.dstColorBlendFactor = VK_BLEND_FACTOR_ONE,
|
||||||
|
.colorBlendOp = VK_BLEND_OP_ADD,
|
||||||
|
.srcAlphaBlendFactor = VK_BLEND_FACTOR_ZERO,
|
||||||
|
.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO,
|
||||||
|
.alphaBlendOp = VK_BLEND_OP_ADD,
|
||||||
|
.colorWriteMask = 0xf
|
||||||
|
};
|
||||||
|
|
||||||
|
if(!NodeStaticOpaquePipeline) {
|
||||||
|
assert(!vkCreateGraphicsPipelines(instance->Graphics.Device, VK_NULL_HANDLE,
|
||||||
|
1, &pipeline, nullptr, &NodeStaticOpaquePipeline));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!NodeStaticTransparentPipeline) {
|
||||||
|
shaderStages[2].module = *NodeShaderFragmentTransparent;
|
||||||
|
|
||||||
|
colorBlend[0] =
|
||||||
|
{
|
||||||
|
.blendEnable = VK_TRUE,
|
||||||
|
.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA,
|
||||||
|
.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
|
||||||
|
.colorBlendOp = VK_BLEND_OP_ADD,
|
||||||
|
.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE,
|
||||||
|
.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO,
|
||||||
|
.alphaBlendOp = VK_BLEND_OP_ADD,
|
||||||
|
.colorWriteMask = 0xf
|
||||||
|
};
|
||||||
|
|
||||||
|
assert(!vkCreateGraphicsPipelines(instance->Graphics.Device, VK_NULL_HANDLE,
|
||||||
|
1, &pipeline, nullptr, &NodeStaticTransparentPipeline));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void VulkanRenderSession::onDefTexture(TextureId_c id, std::vector<std::byte> &&info) {
|
void VulkanRenderSession::onDefTexture(TextureId_c id, std::vector<std::byte> &&info) {
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -60,4 +505,12 @@ void VulkanRenderSession::setCameraPos(WorldId_c worldId, Pos::Object pos, glm::
|
|||||||
Quat = quat;
|
Quat = quat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VulkanRenderSession::beforeDraw() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void VulkanRenderSession::drawWorld(GlobalTime gTime, float dTime, VkCommandBuffer drawCmd) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,23 +1,124 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "Client/Abstract.hpp"
|
#include "Client/Abstract.hpp"
|
||||||
|
#include "Common/Abstract.hpp"
|
||||||
#include <Client/Vulkan/Vulkan.hpp>
|
#include <Client/Vulkan/Vulkan.hpp>
|
||||||
|
#include <glm/ext/matrix_transform.hpp>
|
||||||
|
|
||||||
|
/*
|
||||||
|
У движка есть один текстурный атлас VK_IMAGE_VIEW_TYPE_2D_ARRAY(RGBA_UINT) и к нему Storage с инфой о положении текстур
|
||||||
|
Это общий для всех VkDescriptorSetLayout и VkDescriptorSet
|
||||||
|
|
||||||
|
Для отрисовки вокселей используется карта освещения VK_IMAGE_VIEW_TYPE_2D_ARRAY(RGB_UINT), разделённая по прямоугольным плоскостям
|
||||||
|
Разрешение у этих карт 1м/16
|
||||||
|
|
||||||
|
-- Для всего остального 3д карты освещённости по чанкам в разрешении 1м. 16^3 = 4096 текселей --
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Самые критичные случаи
|
||||||
|
Для вокселей это чередование в шахматном порядке присутствия и отсутствия вокселей
|
||||||
|
Это 8'388'608 вокселя в чанке, общей площадью на картах освещения (256^3/2 *4 *6) 201'326'592 текселей или текстура размером 16к^2
|
||||||
|
Понадобится переиспользование одинаковых участков освещённости
|
||||||
|
Если чанк заполнен слоями вокселей в шахматном порядке по вертикале ((257^2+257*2*4)*128) 8'717'440 текселей или текстура размером 4к^2
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
namespace LV::Client::VK {
|
namespace LV::Client::VK {
|
||||||
|
|
||||||
class VulkanRenderSession : public IRenderSession {
|
struct WorldPCO {
|
||||||
VK::Vulkan *VkInst;
|
glm::mat4 ProjView, Model;
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(sizeof(WorldPCO) == 128);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Воксели рендерятся точками, которые распаковываются в квадратные плоскости
|
||||||
|
|
||||||
|
В чанке по оси 256 вокселей, и 257 позиций вершин (включая дальнюю границу чанка)
|
||||||
|
9 бит на позицию *3 оси = 27 бит
|
||||||
|
Указание материала 16 бит
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct VoxelVertexPoint {
|
||||||
|
uint32_t
|
||||||
|
FX : 9, FY : 9, FZ : 9, // Позиция
|
||||||
|
Place : 3, // Положение распространения xz, xy, zy, и обратные
|
||||||
|
N1 : 1, // Не занято
|
||||||
|
LS : 1, // Масштаб карты освещения (1м/16 или 1м)
|
||||||
|
TX : 8, TY : 8, // Размер+1
|
||||||
|
VoxMtl : 16, // Материал вокселя DefVoxelId_t
|
||||||
|
LU : 14, LV : 14, // Позиция на карте освещения
|
||||||
|
N2 : 2; // Не занято
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Из-за карт освещения индексов не будет
|
||||||
|
Максимальный размер меша 14^3 м от центра ноды
|
||||||
|
Координатное пространство то же, что и у вокселей + 8 позиций с двух сторон
|
||||||
|
Рисуется полигонами
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct NodeVertexStatic {
|
||||||
|
uint32_t
|
||||||
|
FX : 9, FY : 9, FZ : 9, // Позиция -112 ~ 369 / 16
|
||||||
|
N1 : 4, // Не занято
|
||||||
|
LS : 1, // Масштаб карты освещения (1м/16 или 1м)
|
||||||
|
Tex : 18, // Текстура
|
||||||
|
N2 : 14, // Не занято
|
||||||
|
TU : 16, TV : 16; // UV на текстуре
|
||||||
|
};
|
||||||
|
|
||||||
|
class VulkanRenderSession : public IRenderSession, public IVulkanDependent {
|
||||||
|
VK::Vulkan *VkInst = nullptr;
|
||||||
|
// Доступ к миру на стороне клиента
|
||||||
IServerSession *ServerSession = nullptr;
|
IServerSession *ServerSession = nullptr;
|
||||||
|
|
||||||
|
// Положение камеры
|
||||||
WorldId_c WorldId;
|
WorldId_c WorldId;
|
||||||
Pos::Object Pos;
|
Pos::Object Pos;
|
||||||
glm::quat Quat;
|
glm::quat Quat;
|
||||||
|
|
||||||
VK::AtlasImage MainAtlas;
|
/*
|
||||||
|
.binding = 0,
|
||||||
|
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, Текстурный атлас
|
||||||
|
.binding = 1,
|
||||||
|
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, Данные к атласу
|
||||||
|
*/
|
||||||
|
VkDescriptorSetLayout MainAtlasDescLayout = VK_NULL_HANDLE;
|
||||||
|
/*
|
||||||
|
.binding = 2,
|
||||||
|
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, Карта освещения
|
||||||
|
.binding = 3,
|
||||||
|
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, Информация о размерах карты для приведения размеров
|
||||||
|
*/
|
||||||
|
VkDescriptorSetLayout LightMapDescLayout = VK_NULL_HANDLE;
|
||||||
|
|
||||||
|
// Для отрисовки с использованием текстурного атласа и карты освещения
|
||||||
|
VkPipelineLayout MainAtlas_LightMap_PipelineLayout = VK_NULL_HANDLE;
|
||||||
|
|
||||||
|
// Для отрисовки вокселей
|
||||||
|
std::shared_ptr<ShaderModule> VoxelShaderVertex, VoxelShaderGeometry, VoxelShaderFragmentOpaque, VoxelShaderFragmentTransparent;
|
||||||
|
VkPipeline
|
||||||
|
VoxelOpaquePipeline = VK_NULL_HANDLE, // Альфа канал может быть либо 255, либо 0
|
||||||
|
VoxelTransparentPipeline = VK_NULL_HANDLE; // Допускается полупрозрачность и смешивание
|
||||||
|
|
||||||
|
// Для отрисовки статичных, не анимированных нод
|
||||||
|
std::shared_ptr<ShaderModule> NodeShaderVertex, NodeShaderGeometry, NodeShaderFragmentOpaque, NodeShaderFragmentTransparent;
|
||||||
|
VkPipeline
|
||||||
|
NodeStaticOpaquePipeline = VK_NULL_HANDLE,
|
||||||
|
NodeStaticTransparentPipeline = VK_NULL_HANDLE;
|
||||||
|
|
||||||
|
|
||||||
std::map<TextureId_c, uint16_t> ServerToAtlas;
|
std::map<TextureId_c, uint16_t> ServerToAtlas;
|
||||||
|
|
||||||
|
virtual void free(Vulkan *instance) override;
|
||||||
|
virtual void init(Vulkan *instance) override;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
VulkanRenderSession(VK::Vulkan *vkInst);
|
WorldPCO PCO;
|
||||||
|
|
||||||
|
public:
|
||||||
|
VulkanRenderSession();
|
||||||
virtual ~VulkanRenderSession();
|
virtual ~VulkanRenderSession();
|
||||||
|
|
||||||
void setServerSession(IServerSession *serverSession) {
|
void setServerSession(IServerSession *serverSession) {
|
||||||
@@ -38,6 +139,13 @@ public:
|
|||||||
|
|
||||||
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::vector<Pos::GlobalChunk> &changeOrAddList, const std::vector<Pos::GlobalChunk> &remove) override;
|
||||||
virtual void setCameraPos(WorldId_c worldId, Pos::Object pos, glm::quat quat) 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)) {
|
||||||
|
return glm::translate(glm::mat4(quat), camOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void beforeDraw();
|
||||||
|
void drawWorld(GlobalTime gTime, float dTime, VkCommandBuffer drawCmd);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
28
Work/assets/shaders/chunk/node.geom
Normal file
28
Work/assets/shaders/chunk/node.geom
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
#version 450
|
||||||
|
|
||||||
|
layout (triangles) in;
|
||||||
|
layout (triangle_strip, max_vertices = 3) out;
|
||||||
|
|
||||||
|
layout(location = 0) in GeometryObj {
|
||||||
|
vec3 GeoPos; // Реальная позиция в мире
|
||||||
|
uint Texture; // Текстура
|
||||||
|
vec2 UV;
|
||||||
|
} Geometry[];
|
||||||
|
|
||||||
|
layout(location = 0) out FragmentObj {
|
||||||
|
vec3 GeoPos; // Реальная позиция в мире
|
||||||
|
uint Texture; // Текстура
|
||||||
|
vec2 UV;
|
||||||
|
} Fragment;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
for(int iter = 0; iter < 3; iter++) {
|
||||||
|
gl_Position = gl_in[iter].gl_Position;
|
||||||
|
Fragment.GeoPos = Geometry[iter].GeoPos;
|
||||||
|
Fragment.Texture = Geometry[iter].Texture;
|
||||||
|
Fragment.UV = Geometry[iter].UV;
|
||||||
|
EmitVertex();
|
||||||
|
}
|
||||||
|
|
||||||
|
EndPrimitive();
|
||||||
|
}
|
||||||
BIN
Work/assets/shaders/chunk/node.geom.bin
Normal file
BIN
Work/assets/shaders/chunk/node.geom.bin
Normal file
Binary file not shown.
44
Work/assets/shaders/chunk/node.vert
Normal file
44
Work/assets/shaders/chunk/node.vert
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
#version 450
|
||||||
|
|
||||||
|
layout(location = 0) in uvec4 Vertex;
|
||||||
|
|
||||||
|
layout(location = 0) out GeometryObj {
|
||||||
|
vec3 GeoPos; // Реальная позиция в мире
|
||||||
|
uint Texture; // Текстура
|
||||||
|
vec2 UV;
|
||||||
|
} Geometry;
|
||||||
|
|
||||||
|
layout(push_constant) uniform UniformBufferObject {
|
||||||
|
mat4 projview;
|
||||||
|
mat4 model;
|
||||||
|
} ubo;
|
||||||
|
|
||||||
|
|
||||||
|
// struct NodeVertexStatic {
|
||||||
|
// uint32_t
|
||||||
|
// FX : 9, FY : 9, FZ : 9, // Позиция -112 ~ 369 / 16
|
||||||
|
// N1 : 4, // Не занято
|
||||||
|
// LS : 1, // Масштаб карты освещения (1м/16 или 1м)
|
||||||
|
// Tex : 18, // Текстура
|
||||||
|
// N2 : 14, // Не занято
|
||||||
|
// TU : 16, TV : 16; // UV на текстуре
|
||||||
|
// };
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec4 baseVec = ubo.model*vec4(
|
||||||
|
float(Vertex.x & 0x1ff) / 16.f - 7,
|
||||||
|
float((Vertex.x >> 9) & 0x1ff) / 16.f - 7,
|
||||||
|
float((Vertex.x >> 18) & 0x1ff) / 16.f - 7,
|
||||||
|
1
|
||||||
|
);
|
||||||
|
|
||||||
|
Geometry.GeoPos = baseVec.xyz;
|
||||||
|
Geometry.Texture = Vertex.y & 0x3ffff;
|
||||||
|
Geometry.UV = vec2(
|
||||||
|
float(Vertex.z & 0xffff) / pow(2, 16),
|
||||||
|
float((Vertex.z >> 16) & 0xffff) / pow(2, 16)
|
||||||
|
);
|
||||||
|
|
||||||
|
gl_Position = ubo.projview*baseVec;
|
||||||
|
}
|
||||||
BIN
Work/assets/shaders/chunk/node.vert.bin
Normal file
BIN
Work/assets/shaders/chunk/node.vert.bin
Normal file
Binary file not shown.
23
Work/assets/shaders/chunk/node_opaque.frag
Normal file
23
Work/assets/shaders/chunk/node_opaque.frag
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
#version 450
|
||||||
|
|
||||||
|
layout(location = 0) in FragmentObj {
|
||||||
|
vec3 GeoPos; // Реальная позиция в мире
|
||||||
|
uint Texture; // Текстура
|
||||||
|
vec2 UV;
|
||||||
|
} Fragment;
|
||||||
|
|
||||||
|
layout(location = 0) out vec4 Frame;
|
||||||
|
|
||||||
|
uniform layout(set = 0, binding = 0) sampler2DArray MainAtlas;
|
||||||
|
layout(set = 0, binding = 1) readonly buffer MainAtlasLayoutObj {
|
||||||
|
vec3 Color;
|
||||||
|
} MainAtlasLayout;
|
||||||
|
|
||||||
|
uniform layout(set = 1, binding = 0) sampler2DArray LightMap;
|
||||||
|
layout(set = 1, binding = 1) readonly buffer LightMapLayoutObj {
|
||||||
|
vec3 Color;
|
||||||
|
} LightMapLayout;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
Frame = vec4(1);
|
||||||
|
}
|
||||||
BIN
Work/assets/shaders/chunk/node_opaque.frag.bin
Normal file
BIN
Work/assets/shaders/chunk/node_opaque.frag.bin
Normal file
Binary file not shown.
23
Work/assets/shaders/chunk/node_transparent.frag
Normal file
23
Work/assets/shaders/chunk/node_transparent.frag
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
#version 450
|
||||||
|
|
||||||
|
layout(location = 0) in FragmentObj {
|
||||||
|
vec3 GeoPos; // Реальная позиция в мире
|
||||||
|
uint Texture; // Текстура
|
||||||
|
vec2 UV;
|
||||||
|
} Fragment;
|
||||||
|
|
||||||
|
layout(location = 0) out vec4 Frame;
|
||||||
|
|
||||||
|
uniform layout(set = 0, binding = 0) sampler2DArray MainAtlas;
|
||||||
|
layout(set = 0, binding = 1) readonly buffer MainAtlasLayoutObj {
|
||||||
|
vec3 Color;
|
||||||
|
} MainAtlasLayout;
|
||||||
|
|
||||||
|
uniform layout(set = 1, binding = 0) sampler2DArray LightMap;
|
||||||
|
layout(set = 1, binding = 1) readonly buffer LightMapLayoutObj {
|
||||||
|
vec3 Color;
|
||||||
|
} LightMapLayout;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
Frame = vec4(1);
|
||||||
|
}
|
||||||
BIN
Work/assets/shaders/chunk/node_transparent.frag.bin
Normal file
BIN
Work/assets/shaders/chunk/node_transparent.frag.bin
Normal file
Binary file not shown.
244
Work/assets/shaders/chunk/voxel.geom
Normal file
244
Work/assets/shaders/chunk/voxel.geom
Normal file
@@ -0,0 +1,244 @@
|
|||||||
|
#version 450
|
||||||
|
|
||||||
|
layout (points) in;
|
||||||
|
layout (triangle_strip, max_vertices = 4) out;
|
||||||
|
|
||||||
|
layout(location = 0) in highp uvec3 Geometry[];
|
||||||
|
|
||||||
|
layout(location = 0) out Fragment {
|
||||||
|
vec3 GeoPos; // Реальная позиция в мире
|
||||||
|
uint VoxMTL; // Материал вокселя
|
||||||
|
vec2 LUV;
|
||||||
|
} fragment;
|
||||||
|
|
||||||
|
layout(push_constant) uniform UniformBufferObject {
|
||||||
|
mat4 projview;
|
||||||
|
mat4 model;
|
||||||
|
} ubo;
|
||||||
|
|
||||||
|
// struct VoxelVertexPoint {
|
||||||
|
// uint32_t
|
||||||
|
// FX : 9, FY : 9, FZ : 9, // Позиция
|
||||||
|
// Place : 3, // Положение распространения xz, xy, zy, и обратные
|
||||||
|
// N1 : 1, // Не занято
|
||||||
|
// LS : 1, // Масштаб карты освещения (1м/16 или 1м)
|
||||||
|
// TX : 8, TY : 8, // Размер+1
|
||||||
|
// VoxMtl : 16, // Материал вокселя DefVoxelId_t
|
||||||
|
// LU : 14, LV : 14, // Позиция на карте освещения
|
||||||
|
// N2 : 2; // Не занято
|
||||||
|
// };
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vec4 baseVec = vec4(
|
||||||
|
float(Geometry[0].x & 0x1ff) / 16.f,
|
||||||
|
float((Geometry[0].x >> 9) & 0x1ff) / 16.f,
|
||||||
|
float((Geometry[0].x >> 18) & 0x1ff) / 16.f,
|
||||||
|
1
|
||||||
|
);
|
||||||
|
|
||||||
|
vec2 size = vec2(
|
||||||
|
float(Geometry[0].y & 0xff)+1,
|
||||||
|
float((Geometry[0].y >> 8) & 0xff)+1
|
||||||
|
);
|
||||||
|
|
||||||
|
uint voxMTL = ((Geometry[0].y >> 16) & 0xffff);
|
||||||
|
vec2 luv = vec2(float(Geometry[0].z & 0x3fff)+0.5f, float((Geometry[0].z >> 14) & 0x3fff)+0.5f);
|
||||||
|
|
||||||
|
// Стартовая вершина
|
||||||
|
vec4 tempVec = baseVec;
|
||||||
|
tempVec = ubo.model*tempVec;
|
||||||
|
fragment.GeoPos = vec3(tempVec);
|
||||||
|
fragment.VoxMTL = voxMTL;
|
||||||
|
fragment.LUV = luv;
|
||||||
|
gl_Position = ubo.projview*tempVec;
|
||||||
|
EmitVertex();
|
||||||
|
|
||||||
|
|
||||||
|
int place = int(Geometry[0].x >> 27) & 0x3;
|
||||||
|
switch(place) {
|
||||||
|
case 0: // xz
|
||||||
|
tempVec = baseVec;
|
||||||
|
tempVec.x += size.x;
|
||||||
|
tempVec = ubo.model*tempVec;
|
||||||
|
fragment.GeoPos = vec3(tempVec);
|
||||||
|
fragment.VoxMTL = voxMTL;
|
||||||
|
fragment.LUV = luv+vec2(size.x, 0);
|
||||||
|
gl_Position = ubo.projview*tempVec;
|
||||||
|
EmitVertex();
|
||||||
|
|
||||||
|
tempVec = baseVec;
|
||||||
|
tempVec.z += size.y;
|
||||||
|
tempVec = ubo.model*tempVec;
|
||||||
|
fragment.GeoPos = vec3(tempVec);
|
||||||
|
fragment.VoxMTL = voxMTL;
|
||||||
|
fragment.LUV = luv+vec2(0, size.y);
|
||||||
|
gl_Position = ubo.projview*tempVec;
|
||||||
|
EmitVertex();
|
||||||
|
|
||||||
|
tempVec = baseVec;
|
||||||
|
tempVec.x += size.x;
|
||||||
|
tempVec.z += size.y;
|
||||||
|
tempVec = ubo.model*tempVec;
|
||||||
|
fragment.GeoPos = vec3(tempVec);
|
||||||
|
fragment.VoxMTL = voxMTL;
|
||||||
|
fragment.LUV = luv+vec2(size.x, size.y);
|
||||||
|
gl_Position = ubo.projview*tempVec;
|
||||||
|
EmitVertex();
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 1: // xy
|
||||||
|
tempVec = baseVec;
|
||||||
|
tempVec.x += size.x;
|
||||||
|
tempVec = ubo.model*tempVec;
|
||||||
|
fragment.GeoPos = vec3(tempVec);
|
||||||
|
fragment.VoxMTL = voxMTL;
|
||||||
|
fragment.LUV = luv+vec2(size.x, 0);
|
||||||
|
gl_Position = ubo.projview*tempVec;
|
||||||
|
EmitVertex();
|
||||||
|
|
||||||
|
tempVec = baseVec;
|
||||||
|
tempVec.y += size.y;
|
||||||
|
tempVec = ubo.model*tempVec;
|
||||||
|
fragment.GeoPos = vec3(tempVec);
|
||||||
|
fragment.VoxMTL = voxMTL;
|
||||||
|
fragment.LUV = luv+vec2(0, size.y);
|
||||||
|
gl_Position = ubo.projview*tempVec;
|
||||||
|
EmitVertex();
|
||||||
|
|
||||||
|
tempVec = baseVec;
|
||||||
|
tempVec.x += size.x;
|
||||||
|
tempVec.y += size.y;
|
||||||
|
tempVec = ubo.model*tempVec;
|
||||||
|
fragment.GeoPos = vec3(tempVec);
|
||||||
|
fragment.VoxMTL = voxMTL;
|
||||||
|
fragment.LUV = luv+vec2(size.x, size.y);
|
||||||
|
gl_Position = ubo.projview*tempVec;
|
||||||
|
EmitVertex();
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 2: // zy
|
||||||
|
tempVec = baseVec;
|
||||||
|
tempVec.z += size.x;
|
||||||
|
tempVec = ubo.model*tempVec;
|
||||||
|
fragment.GeoPos = vec3(tempVec);
|
||||||
|
fragment.VoxMTL = voxMTL;
|
||||||
|
fragment.LUV = luv+vec2(size.x, 0);
|
||||||
|
gl_Position = ubo.projview*tempVec;
|
||||||
|
EmitVertex();
|
||||||
|
|
||||||
|
tempVec = baseVec;
|
||||||
|
tempVec.y += size.y;
|
||||||
|
tempVec = ubo.model*tempVec;
|
||||||
|
fragment.GeoPos = vec3(tempVec);
|
||||||
|
fragment.VoxMTL = voxMTL;
|
||||||
|
fragment.LUV = luv+vec2(0, size.y);
|
||||||
|
gl_Position = ubo.projview*tempVec;
|
||||||
|
EmitVertex();
|
||||||
|
|
||||||
|
tempVec = baseVec;
|
||||||
|
tempVec.z += size.x;
|
||||||
|
tempVec.y += size.y;
|
||||||
|
tempVec = ubo.model*tempVec;
|
||||||
|
fragment.GeoPos = vec3(tempVec);
|
||||||
|
fragment.VoxMTL = voxMTL;
|
||||||
|
fragment.LUV = luv+vec2(size.x, size.y);
|
||||||
|
gl_Position = ubo.projview*tempVec;
|
||||||
|
EmitVertex();
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 3: // xz inv
|
||||||
|
tempVec = baseVec;
|
||||||
|
tempVec.z += size.y;
|
||||||
|
tempVec = ubo.model*tempVec;
|
||||||
|
fragment.GeoPos = vec3(tempVec);
|
||||||
|
fragment.VoxMTL = voxMTL;
|
||||||
|
fragment.LUV = luv+vec2(size.x, 0);
|
||||||
|
gl_Position = ubo.projview*tempVec;
|
||||||
|
EmitVertex();
|
||||||
|
|
||||||
|
tempVec = baseVec;
|
||||||
|
tempVec.x += size.x;
|
||||||
|
tempVec = ubo.model*tempVec;
|
||||||
|
fragment.GeoPos = vec3(tempVec);
|
||||||
|
fragment.VoxMTL = voxMTL;
|
||||||
|
fragment.LUV = luv+vec2(0, size.y);
|
||||||
|
gl_Position = ubo.projview*tempVec;
|
||||||
|
EmitVertex();
|
||||||
|
|
||||||
|
tempVec = baseVec;
|
||||||
|
tempVec.x += size.x;
|
||||||
|
tempVec.z += size.y;
|
||||||
|
tempVec = ubo.model*tempVec;
|
||||||
|
fragment.GeoPos = vec3(tempVec);
|
||||||
|
fragment.VoxMTL = voxMTL;
|
||||||
|
fragment.LUV = luv+vec2(size.x, size.y);
|
||||||
|
gl_Position = ubo.projview*tempVec;
|
||||||
|
EmitVertex();
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 4: // xy inv
|
||||||
|
tempVec = baseVec;
|
||||||
|
tempVec.y += size.y;
|
||||||
|
tempVec = ubo.model*tempVec;
|
||||||
|
fragment.GeoPos = vec3(tempVec);
|
||||||
|
fragment.VoxMTL = voxMTL;
|
||||||
|
fragment.LUV = luv+vec2(size.x, 0);
|
||||||
|
gl_Position = ubo.projview*tempVec;
|
||||||
|
EmitVertex();
|
||||||
|
|
||||||
|
tempVec = baseVec;
|
||||||
|
tempVec.x += size.x;
|
||||||
|
tempVec = ubo.model*tempVec;
|
||||||
|
fragment.GeoPos = vec3(tempVec);
|
||||||
|
fragment.VoxMTL = voxMTL;
|
||||||
|
fragment.LUV = luv+vec2(0, size.y);
|
||||||
|
gl_Position = ubo.projview*tempVec;
|
||||||
|
EmitVertex();
|
||||||
|
|
||||||
|
tempVec = baseVec;
|
||||||
|
tempVec.x += size.x;
|
||||||
|
tempVec.y += size.y;
|
||||||
|
tempVec = ubo.model*tempVec;
|
||||||
|
fragment.GeoPos = vec3(tempVec);
|
||||||
|
fragment.VoxMTL = voxMTL;
|
||||||
|
fragment.LUV = luv+vec2(size.x, size.y);
|
||||||
|
gl_Position = ubo.projview*tempVec;
|
||||||
|
EmitVertex();
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 5: // zy inv
|
||||||
|
tempVec = baseVec;
|
||||||
|
tempVec.y += size.y;
|
||||||
|
tempVec = ubo.model*tempVec;
|
||||||
|
fragment.GeoPos = vec3(tempVec);
|
||||||
|
fragment.VoxMTL = voxMTL;
|
||||||
|
fragment.LUV = luv+vec2(size.x, 0);
|
||||||
|
gl_Position = ubo.projview*tempVec;
|
||||||
|
EmitVertex();
|
||||||
|
|
||||||
|
tempVec = baseVec;
|
||||||
|
tempVec.z += size.x;
|
||||||
|
tempVec = ubo.model*tempVec;
|
||||||
|
fragment.GeoPos = vec3(tempVec);
|
||||||
|
fragment.VoxMTL = voxMTL;
|
||||||
|
fragment.LUV = luv+vec2(0, size.y);
|
||||||
|
gl_Position = ubo.projview*tempVec;
|
||||||
|
EmitVertex();
|
||||||
|
|
||||||
|
tempVec = baseVec;
|
||||||
|
tempVec.z += size.x;
|
||||||
|
tempVec.y += size.y;
|
||||||
|
tempVec = ubo.model*tempVec;
|
||||||
|
fragment.GeoPos = vec3(tempVec);
|
||||||
|
fragment.VoxMTL = voxMTL;
|
||||||
|
fragment.LUV = luv+vec2(size.x, size.y);
|
||||||
|
gl_Position = ubo.projview*tempVec;
|
||||||
|
EmitVertex();
|
||||||
|
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
EndPrimitive();
|
||||||
|
}
|
||||||
BIN
Work/assets/shaders/chunk/voxel.geom.bin
Normal file
BIN
Work/assets/shaders/chunk/voxel.geom.bin
Normal file
Binary file not shown.
10
Work/assets/shaders/chunk/voxel.vert
Normal file
10
Work/assets/shaders/chunk/voxel.vert
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#version 450
|
||||||
|
|
||||||
|
layout(location = 0) in uvec3 Vertex;
|
||||||
|
layout(location = 0) out uvec3 Geometry;
|
||||||
|
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
Geometry = Vertex;
|
||||||
|
}
|
||||||
BIN
Work/assets/shaders/chunk/voxel.vert.bin
Normal file
BIN
Work/assets/shaders/chunk/voxel.vert.bin
Normal file
Binary file not shown.
23
Work/assets/shaders/chunk/voxel_opaque.frag
Normal file
23
Work/assets/shaders/chunk/voxel_opaque.frag
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
#version 450
|
||||||
|
|
||||||
|
layout(location = 0) in Fragment {
|
||||||
|
vec3 GeoPos; // Реальная позиция в мире
|
||||||
|
uint VoxMTL; // Материал вокселя
|
||||||
|
vec2 LUV;
|
||||||
|
} fragment;
|
||||||
|
|
||||||
|
layout(location = 0) out vec4 Frame;
|
||||||
|
|
||||||
|
uniform layout(set = 0, binding = 0) sampler2DArray MainAtlas;
|
||||||
|
layout(set = 0, binding = 1) readonly buffer MainAtlasLayoutObj {
|
||||||
|
vec3 Color;
|
||||||
|
} MainAtlasLayout;
|
||||||
|
|
||||||
|
uniform layout(set = 1, binding = 0) sampler2DArray LightMap;
|
||||||
|
layout(set = 1, binding = 1) readonly buffer LightMapLayoutObj {
|
||||||
|
vec3 Color;
|
||||||
|
} LightMapLayout;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
Frame = vec4(1);
|
||||||
|
}
|
||||||
BIN
Work/assets/shaders/chunk/voxel_opaque.frag.bin
Normal file
BIN
Work/assets/shaders/chunk/voxel_opaque.frag.bin
Normal file
Binary file not shown.
23
Work/assets/shaders/chunk/voxel_transparent.frag
Normal file
23
Work/assets/shaders/chunk/voxel_transparent.frag
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
#version 450
|
||||||
|
|
||||||
|
layout(location = 0) in Fragment {
|
||||||
|
vec3 GeoPos; // Реальная позиция в мире
|
||||||
|
uint VoxMTL; // Материал вокселя
|
||||||
|
vec2 LUV;
|
||||||
|
} fragment;
|
||||||
|
|
||||||
|
layout(location = 0) out vec4 Frame;
|
||||||
|
|
||||||
|
uniform layout(set = 0, binding = 0) sampler2DArray MainAtlas;
|
||||||
|
layout(set = 0, binding = 1) readonly buffer MainAtlasLayoutObj {
|
||||||
|
vec3 Color;
|
||||||
|
} MainAtlasLayout;
|
||||||
|
|
||||||
|
uniform layout(set = 1, binding = 0) sampler2DArray LightMap;
|
||||||
|
layout(set = 1, binding = 1) readonly buffer LightMapLayoutObj {
|
||||||
|
vec3 Color;
|
||||||
|
} LightMapLayout;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
Frame = vec4(1);
|
||||||
|
}
|
||||||
BIN
Work/assets/shaders/chunk/voxel_transparent.frag.bin
Normal file
BIN
Work/assets/shaders/chunk/voxel_transparent.frag.bin
Normal file
Binary file not shown.
18
Work/assets/shaders/compile.sh
Executable file
18
Work/assets/shaders/compile.sh
Executable file
@@ -0,0 +1,18 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
function compile_shaders() {
|
||||||
|
local source_dir="$1"
|
||||||
|
|
||||||
|
for item in "$source_dir"/*; do
|
||||||
|
filename=$(basename "$item")
|
||||||
|
if [ -d "$item" ]; then
|
||||||
|
compile_shaders "$source_dir"/"$filename"
|
||||||
|
|
||||||
|
elif [ -f "$item" ] && [ $item -nt $item.bin ] && ([[ $filename = *'.frag' ]] || [[ $filename = *'.vert' ]] || [[ $filename = *'.geom' ]]); then
|
||||||
|
echo $filename
|
||||||
|
glslc $item -o $item.bin --target-env=vulkan1.2
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
compile_shaders .
|
||||||
Reference in New Issue
Block a user