diff options
-rw-r--r-- | .gitignore | 6 | ||||
-rw-r--r-- | CMakeLists.txt | 2 | ||||
-rw-r--r-- | cwd/assets/altcraft/scripts/blocks.lua | 10 | ||||
-rw-r--r-- | cwd/assets/altcraft/shaders/frag/fwd_liquid_face.fs | 38 | ||||
-rw-r--r-- | cwd/assets/altcraft/shaders/frag/liquid_face.fs | 22 | ||||
-rw-r--r-- | cwd/assets/altcraft/shaders/vert/liquid_face.vs | 38 | ||||
-rw-r--r-- | cwd/assets/minecraft/blockstates/lava.json | 5 | ||||
-rw-r--r-- | cwd/assets/minecraft/blockstates/water.json | 5 | ||||
-rw-r--r-- | cwd/assets/minecraft/models/block/lava.json | 6 | ||||
-rw-r--r-- | cwd/assets/minecraft/models/block/water.json | 6 | ||||
-rw-r--r-- | src/AssetManager.cpp | 47 | ||||
-rw-r--r-- | src/AssetManager.hpp | 9 | ||||
-rw-r--r-- | src/Block.cpp | 32 | ||||
-rw-r--r-- | src/Block.hpp | 9 | ||||
-rw-r--r-- | src/Plugin.cpp | 8 | ||||
-rw-r--r-- | src/RendererSection.cpp | 54 | ||||
-rw-r--r-- | src/RendererSection.hpp | 25 | ||||
-rw-r--r-- | src/RendererSectionData.cpp | 255 | ||||
-rw-r--r-- | src/RendererSectionData.hpp | 3 | ||||
-rw-r--r-- | src/RendererWorld.cpp | 69 | ||||
-rw-r--r-- | src/RendererWorld.hpp | 6 |
21 files changed, 566 insertions, 89 deletions
@@ -1,5 +1,7 @@ cwd/assets/minecraft cwd/assets/altcraft/fonts/ +cwd/myeasylog.log +cwd/settings.json build/ #CLion @@ -10,6 +12,10 @@ cmake-build-release/ #Visual Studio .vs/ CMakeSettings.json +Folder.DotSettings.user + +#Visual Studio Code +.vscode/ #Qt Creator CMakeLists.txt.user diff --git a/CMakeLists.txt b/CMakeLists.txt index f70a096..240d899 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -217,4 +217,4 @@ if(MSVC AND CMAKE_BUILD_TYPE MATCHES Release) set_target_properties(AltCraft PROPERTIES WIN32_EXECUTABLE ON) endif() -file(DOWNLOAD https://github.com/google/fonts/raw/main/apache/opensans/OpenSans%5Bwdth%2Cwght%5D.ttf ${CMAKE_SOURCE_DIR}/cwd/assets/altcraft/fonts/OpenSans-Regular.ttf) +file(DOWNLOAD https://github.com/google/fonts/raw/main/ofl/opensans/OpenSans%5Bwdth%2Cwght%5D.ttf ${CMAKE_SOURCE_DIR}/cwd/assets/altcraft/fonts/OpenSans-Regular.ttf) diff --git a/cwd/assets/altcraft/scripts/blocks.lua b/cwd/assets/altcraft/scripts/blocks.lua index 5678677..dde4b57 100644 --- a/cwd/assets/altcraft/scripts/blocks.lua +++ b/cwd/assets/altcraft/scripts/blocks.lua @@ -33,13 +33,11 @@ local function RegisterBlocks() AC.RegisterBlock(BlockId.new(7,0), true, "bedrock", "normal") - AC.RegisterBlock(BlockId.new(8,0), true, "water", "normal") + AC.RegisterLiquid(BlockId.new(8,0), "blocks/water_flow", "blocks/water_still") + AC.RegisterLiquid(BlockId.new(9,0), "blocks/water_flow", "blocks/water_still") - AC.RegisterBlock(BlockId.new(9,0), true, "water", "normal") - - AC.RegisterBlock(BlockId.new(10,0), true, "lava", "normal") - - AC.RegisterBlock(BlockId.new(11,0), true, "lava", "normal") + AC.RegisterLiquid(BlockId.new(10,0), "blocks/lava_flow", "blocks/lava_still") + AC.RegisterLiquid(BlockId.new(11,0), "blocks/lava_flow", "blocks/lava_still") AC.RegisterBlock(BlockId.new(12,0), true, "sand", "normal") AC.RegisterBlock(BlockId.new(12,1), true, "red_sand", "normal") diff --git a/cwd/assets/altcraft/shaders/frag/fwd_liquid_face.fs b/cwd/assets/altcraft/shaders/frag/fwd_liquid_face.fs new file mode 100644 index 0000000..f8d9376 --- /dev/null +++ b/cwd/assets/altcraft/shaders/frag/fwd_liquid_face.fs @@ -0,0 +1,38 @@ +#version 330 core + +in vec4 faceWorldPos; +in vec3 faceTextureUv; +in vec3 faceAddColor; +in vec3 faceNormal; +in vec2 faceLight; + +out vec4 fragColor; + +uniform sampler2DArray textureAtlas; + +layout (std140) uniform Globals { + mat4 projView; + mat4 proj; + mat4 invProj; + mat4 view; + uvec2 viewportSize; + vec4 ssaoKernels[64]; + float globalTime; + float dayTime; + float gamma; +}; + +void main() { + vec4 col = texture(textureAtlas, faceTextureUv); + + float localLight = faceLight.r / 15.0f; + float skyLight = faceLight.g / 15.0f; + float lightLevel = clamp(localLight + skyLight * dayTime, 0.01f, 1.0f); + lightLevel = pow(lightLevel, 3); + lightLevel = clamp(lightLevel, 0.005f, 1.0f); + + fragColor = vec4(col.rgb * faceAddColor.rgb * lightLevel, 1.0f); + + fragColor.rgb = pow(fragColor.rgb, vec3(1.0f / gamma)); + fragColor.a = col.a; +} diff --git a/cwd/assets/altcraft/shaders/frag/liquid_face.fs b/cwd/assets/altcraft/shaders/frag/liquid_face.fs new file mode 100644 index 0000000..3e5c0d4 --- /dev/null +++ b/cwd/assets/altcraft/shaders/frag/liquid_face.fs @@ -0,0 +1,22 @@ +#version 330 core + +in vec3 faceTextureUv; +in vec3 faceAddColor; +in vec3 faceNormal; +in vec2 faceLight; +in float faceAmbientOcclusion; + +layout (location = 0) out vec4 color; +layout (location = 1) out vec4 normal; +layout (location = 2) out vec4 light; + +uniform sampler2DArray textureAtlas; + +void main() { + vec4 col = texture(textureAtlas, faceTextureUv); + + color = vec4(col.rgb * faceAddColor.rgb, 1.0f); + normal = vec4(faceNormal, 1.0f); + light = vec4(faceLight / 15.0f, faceAmbientOcclusion, 1.0f); + color.a = col.a; +} diff --git a/cwd/assets/altcraft/shaders/vert/liquid_face.vs b/cwd/assets/altcraft/shaders/vert/liquid_face.vs new file mode 100644 index 0000000..101e4d0 --- /dev/null +++ b/cwd/assets/altcraft/shaders/vert/liquid_face.vs @@ -0,0 +1,38 @@ +#version 330 core + +in vec3 pos[4]; +in vec2 uv[4]; +in vec2 light[4]; +in vec3 normal; +in vec3 color; +in vec3 layerAnimationAo; + +out vec3 faceTextureUv; +out vec3 faceNormal; +out vec3 faceAddColor; +out vec2 faceLight; +out float faceAmbientOcclusion; + +layout (std140) uniform Globals { + mat4 projView; + mat4 proj; + mat4 invProj; + mat4 view; + uvec2 viewportSize; + vec4 ssaoKernels[64]; + float globalTime; + float dayTime; + float gamma; +}; + +void main() { + gl_Position = projView * vec4(pos[gl_VertexID], 1.0f); + + faceTextureUv = vec3(uv[gl_VertexID], layerAnimationAo.r); + faceTextureUv.y -= (uv[2].y - uv[0].y) * trunc(mod(globalTime * 4.0f, layerAnimationAo.g)); + + faceNormal = (view * vec4(normal, 0.0f)).xyz; + faceAddColor = color; + faceLight = light[gl_VertexID]; + faceAmbientOcclusion = layerAnimationAo.b; +} diff --git a/cwd/assets/minecraft/blockstates/lava.json b/cwd/assets/minecraft/blockstates/lava.json deleted file mode 100644 index 97b01d3..0000000 --- a/cwd/assets/minecraft/blockstates/lava.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "variants": { - "normal": { "model": "lava" } - } -} diff --git a/cwd/assets/minecraft/blockstates/water.json b/cwd/assets/minecraft/blockstates/water.json deleted file mode 100644 index 683334a..0000000 --- a/cwd/assets/minecraft/blockstates/water.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "variants": { - "normal": { "model": "water" } - } -} diff --git a/cwd/assets/minecraft/models/block/lava.json b/cwd/assets/minecraft/models/block/lava.json deleted file mode 100644 index 714d0b2..0000000 --- a/cwd/assets/minecraft/models/block/lava.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "block/cube_all", - "textures": { - "all": "blocks/lava_flow" - } -} diff --git a/cwd/assets/minecraft/models/block/water.json b/cwd/assets/minecraft/models/block/water.json deleted file mode 100644 index 860815a..0000000 --- a/cwd/assets/minecraft/models/block/water.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "block/cube_all", - "textures": { - "all": "blocks/water_flow" - } -} diff --git a/src/AssetManager.cpp b/src/AssetManager.cpp index 3e3f677..09f5209 100644 --- a/src/AssetManager.cpp +++ b/src/AssetManager.cpp @@ -573,6 +573,52 @@ BlockFaces &AssetManager::GetBlockModelByBlockId(BlockId block) { return it->second; BlockInfo *blockInfo = GetBlockInfo(block); + if (blockInfo->blockstate == "@liquid") { + BlockFaces blockFaces; + blockFaces.isBlock = false; + blockFaces.isLiquid = true; + blockFaces.transform = glm::mat4(1.0f); + blockFaces.ambientOcclusion = false; + for (size_t i = 0; i < FaceDirection::none; i++) { + blockFaces.faceDirectionVector[i] = FaceDirectionVector[i]; + } + + const auto& liquidInfo = GetBlockLiquidInfo(BlockId{ block.id, 0 }); + + { + AssetTexture* assetTexture = AssetManager::GetAsset<AssetTexture>("minecraft/textures/" + liquidInfo.flowTexture); + if (!assetTexture) + return errorFaces; + TextureCoord texture = atlas->GetTexture(assetTexture->id); + float textureFrames = assetTexture->frames; + blockFaces.faces.emplace_back(ParsedFace{ + FaceDirection::none, + glm::translate(glm::mat4(1.0f), glm::vec3{0.0f, 1.0f, 0.0f}), + glm::vec4{ texture.x,texture.y,texture.w,texture.h }, + static_cast<float>(texture.layer), + static_cast<float>(assetTexture->frames), + glm::vec3(1.0f), + }); + } + + { + AssetTexture* assetTexture = AssetManager::GetAsset<AssetTexture>("minecraft/textures/" + liquidInfo.stillTexture); + if (!assetTexture) + return errorFaces; + TextureCoord texture = atlas->GetTexture(assetTexture->id); + float textureFrames = assetTexture->frames; + blockFaces.faces.emplace_back(ParsedFace{ + FaceDirection::none, + glm::translate(glm::mat4(1.0f), glm::vec3{0.0f, 1.0f, 0.0f}), + glm::vec4{ texture.x,texture.y,texture.w,texture.h }, + static_cast<float>(texture.layer), + static_cast<float>(assetTexture->frames), + glm::vec3(1.0f), + }); + } + + return blockIdToBlockFaces.insert(std::make_pair(block, blockFaces)).first->second; + } AssetBlockState *asset = GetAsset<AssetBlockState>("/minecraft/blockstates/" + blockInfo->blockstate); if (!asset) return errorFaces; @@ -595,6 +641,7 @@ BlockFaces &AssetManager::GetBlockModelByBlockId(BlockId block) { blockFaces.faces = assetModel->blockModel.parsedFaces; blockFaces.isBlock = assetModel->blockModel.IsBlock; blockFaces.ambientOcclusion = assetModel->blockModel.AmbientOcclusion; + blockFaces.isLiquid = false; glm::mat4 transform = glm::mat4(1.0); if (model.y != 0) { diff --git a/src/AssetManager.hpp b/src/AssetManager.hpp index 59fc851..250524e 100644 --- a/src/AssetManager.hpp +++ b/src/AssetManager.hpp @@ -22,6 +22,10 @@ enum FaceDirection { south, west, east, + northWest, + northEast, + southWest, + southEast, none, }; @@ -32,6 +36,10 @@ static const Vector FaceDirectionVector[] = { Vector(0,0,1), Vector(-1,0,0), Vector(1,0,0), + Vector(-1,0,-1), + Vector(1,0,-1), + Vector(-1,0,1), + Vector(1,0,1), Vector(0,0,0) }; @@ -49,6 +57,7 @@ struct BlockFaces { std::vector<ParsedFace> faces; bool isBlock; bool ambientOcclusion; + bool isLiquid; //if true, then faces contains only two elements with valid texture data Vector faceDirectionVector[FaceDirection::none]; }; diff --git a/src/Block.cpp b/src/Block.cpp index 85870f6..8af5a4b 100644 --- a/src/Block.cpp +++ b/src/Block.cpp @@ -1,25 +1,29 @@ #include "Block.hpp" #include <map> -#include <vector> -#include "Plugin.hpp" +static std::map<BlockId, BlockInfo> blocks; +static std::map<BlockId, LiquidInfo> liquids; -static std::vector<BlockInfo> blocks; -static std::map<BlockId, size_t> staticBlockInfo; - -BlockInfo WTFBlock{ true, "", "" }; +static BlockInfo UnknownBlock{ true, "", "" }; +static LiquidInfo UnknownLiquid{ "", "" }; void RegisterStaticBlockInfo(BlockId blockId, BlockInfo blockInfo) { - //NOTE: It can be made thread-safe by using atomic incrementer - staticBlockInfo[blockId] = blocks.size(); - blocks.push_back(blockInfo); + blocks.emplace(blockId, blockInfo); +} + +void RegisterStaticLiquidInfo(BlockId blockId, LiquidInfo liquidInfo) { + liquids[blockId] = liquidInfo; + for (uint8_t i = 0; i < 16; i++) + blocks.emplace(BlockId{ blockId.id, i }, BlockInfo{ true, "@liquid", liquidInfo.stillTexture }); } BlockInfo* GetBlockInfo(BlockId blockId) { - auto it = staticBlockInfo.find(blockId); - if (it != staticBlockInfo.end()) - return &blocks.data()[it->second]; - else - return &WTFBlock; + auto it = blocks.find(blockId); + return it != blocks.end() ? &it->second : &UnknownBlock; +} + +const LiquidInfo& GetBlockLiquidInfo(BlockId blockId) { + auto it = liquids.find(blockId); + return it != liquids.end() ? it->second : UnknownLiquid; } diff --git a/src/Block.hpp b/src/Block.hpp index 0fd0e89..535ae68 100644 --- a/src/Block.hpp +++ b/src/Block.hpp @@ -47,6 +47,15 @@ struct BlockInfo { std::string variant; }; +struct LiquidInfo { + std::string flowTexture; + std::string stillTexture; +}; + void RegisterStaticBlockInfo(BlockId blockId, BlockInfo blockInfo); +void RegisterStaticLiquidInfo(BlockId blockId, LiquidInfo liquidInfo); + BlockInfo* GetBlockInfo(BlockId blockId); + +const LiquidInfo& GetBlockLiquidInfo(BlockId blockId); diff --git a/src/Plugin.cpp b/src/Plugin.cpp index 3e06b0c..7a3b716 100644 --- a/src/Plugin.cpp +++ b/src/Plugin.cpp @@ -78,6 +78,13 @@ namespace PluginApi { }); } + void RegisterLiquid(BlockId blockId, std::string flowTexture, std::string stillTexture) { + RegisterStaticLiquidInfo(blockId, LiquidInfo{ + flowTexture, + stillTexture + }); + } + void RegisterDimension(int dimId, Dimension dim) { RegisterNewDimension(dimId, dim); } @@ -286,6 +293,7 @@ void PluginSystem::Init() { apiTable["LogError"] = PluginApi::LogError; apiTable["GetGameState"] = PluginApi::GetGameState; apiTable["RegisterBlock"] = PluginApi::RegisterBlock; + apiTable["RegisterLiquid"] = PluginApi::RegisterLiquid; apiTable["RegisterDimension"] = PluginApi::RegisterDimension; apiTable["ConnectToServer"] = PluginApi::ConnectToServer; apiTable["Exit"] = PluginApi::Exit; diff --git a/src/RendererSection.cpp b/src/RendererSection.cpp index 429a8bd..7ea74df 100644 --- a/src/RendererSection.cpp +++ b/src/RendererSection.cpp @@ -9,16 +9,26 @@ #include "RendererSectionData.hpp" -RendererSection::RendererSection(const RendererSectionData& data, std::shared_ptr<Gal::Pipeline> pipeline, std::shared_ptr<Gal::BufferBinding> bufferBinding) { +RendererSection::RendererSection(const RendererSectionData& data, + std::shared_ptr<Gal::Pipeline> solidPipeline, + std::shared_ptr<Gal::BufferBinding> solidBufferBinding, + std::shared_ptr<Gal::Pipeline> liquidPipeline, + std::shared_ptr<Gal::BufferBinding> liquidBufferBinding) { OPTICK_EVENT(); auto gal = Gal::GetImplementation(); - buffer = gal->CreateBuffer(); - pipelineInstance = pipeline->CreateInstance({ - {bufferBinding, buffer} + solidBuffer = gal->CreateBuffer(); + solidPipelineInstance = solidPipeline->CreateInstance({ + {solidBufferBinding, solidBuffer} }); - pipelineInstance->SetInstancesCount(4); + solidPipelineInstance->SetInstancesCount(4); + + liquidBuffer = gal->CreateBuffer(); + liquidPipelineInstance = liquidPipeline->CreateInstance({ + {liquidBufferBinding, liquidBuffer} + }); + liquidPipelineInstance->SetInstancesCount(4); UpdateData(data); } @@ -32,18 +42,27 @@ RendererSection::~RendererSection() { } -void swap(RendererSection & lhs, RendererSection & rhs) { - std::swap(lhs.pipelineInstance, rhs.pipelineInstance); - std::swap(lhs.buffer, rhs.buffer); - std::swap(lhs.hash, rhs.hash); - std::swap(lhs.numOfFaces, rhs.numOfFaces); - std::swap(lhs.sectionPos, rhs.sectionPos); +void RendererSection::RenderSolid() { + OPTICK_EVENT(); + solidPipelineInstance->Activate(); + solidPipelineInstance->Render(0, solidFacesCount); } -void RendererSection::Render() { +void RendererSection::RenderLiquid() { OPTICK_EVENT(); - pipelineInstance->Activate(); - pipelineInstance->Render(0, numOfFaces); + liquidPipelineInstance->Activate(); + liquidPipelineInstance->Render(0, liquidFacesCount); +} + +void swap(RendererSection & lhs, RendererSection & rhs) { + std::swap(lhs.solidPipelineInstance, rhs.solidPipelineInstance); + std::swap(lhs.solidBuffer, rhs.solidBuffer); + std::swap(lhs.liquidPipelineInstance, rhs.liquidPipelineInstance); + std::swap(lhs.liquidBuffer, rhs.liquidBuffer); + std::swap(lhs.hash, rhs.hash); + std::swap(lhs.solidFacesCount, rhs.solidFacesCount); + std::swap(lhs.liquidFacesCount, rhs.liquidFacesCount); + std::swap(lhs.sectionPos, rhs.sectionPos); } Vector RendererSection::GetPosition() { @@ -57,9 +76,12 @@ size_t RendererSection::GetHash() { void RendererSection::UpdateData(const RendererSectionData & data) { OPTICK_EVENT(); - buffer->SetData({ reinterpret_cast<const std::byte*>(data.vertices.data()), reinterpret_cast<const std::byte*>(data.vertices.data() + data.vertices.size())}); + solidBuffer->SetData({ reinterpret_cast<const std::byte*>(data.solidVertices.data()), reinterpret_cast<const std::byte*>(data.solidVertices.data() + data.solidVertices.size())}); + solidFacesCount = data.solidVertices.size(); + + liquidBuffer->SetData({ reinterpret_cast<const std::byte*>(data.liquidVertices.data()), reinterpret_cast<const std::byte*>(data.liquidVertices.data() + data.liquidVertices.size()) }); + liquidFacesCount = data.liquidVertices.size(); - numOfFaces = data.vertices.size(); sectionPos = data.sectionPos; hash = data.hash; } diff --git a/src/RendererSection.hpp b/src/RendererSection.hpp index 0a03f44..8125e4e 100644 --- a/src/RendererSection.hpp +++ b/src/RendererSection.hpp @@ -7,26 +7,39 @@ class RenderState; class RendererSectionData; class RendererSection { - std::shared_ptr<Gal::PipelineInstance> pipelineInstance; - std::shared_ptr<Gal::Buffer> buffer; - size_t hash; + std::shared_ptr<Gal::PipelineInstance> solidPipelineInstance; + std::shared_ptr<Gal::Buffer> solidBuffer; + std::shared_ptr<Gal::PipelineInstance> liquidPipelineInstance; + std::shared_ptr<Gal::Buffer> liquidBuffer; Vector sectionPos; + size_t hash = 0; + size_t solidFacesCount = 0; + size_t liquidFacesCount = 0; RendererSection(const RendererSection &other) = delete; public: - RendererSection(const RendererSectionData& data, std::shared_ptr<Gal::Pipeline> pipeline, std::shared_ptr<Gal::BufferBinding> bufferBinding); + RendererSection( + const RendererSectionData& data, + std::shared_ptr<Gal::Pipeline> solidPipeline, + std::shared_ptr<Gal::BufferBinding> solidBufferBinding, + std::shared_ptr<Gal::Pipeline> liquidPipeline, + std::shared_ptr<Gal::BufferBinding> liquidBufferBinding); RendererSection(RendererSection &&other); ~RendererSection(); - void Render(); + void RenderSolid(); + + void RenderLiquid(); Vector GetPosition(); size_t GetHash(); - size_t numOfFaces; + inline size_t GetSolidFacesCount() { return solidFacesCount; } + + inline size_t GetLiquidFacesCount() { return liquidFacesCount; } friend void swap(RendererSection &lhs, RendererSection &rhs); diff --git a/src/RendererSectionData.cpp b/src/RendererSectionData.cpp index 761dd14..fdd961d 100644 --- a/src/RendererSectionData.cpp +++ b/src/RendererSectionData.cpp @@ -79,8 +79,8 @@ void AddFacesByBlockModel(RendererSectionData& data, const BlockFaces& model, co continue; } - data.vertices.emplace_back(); - VertexData& vertexData = data.vertices.back(); + data.solidVertices.emplace_back(); + VertexData& vertexData = data.solidVertices.back(); glm::mat4 transformed = transform * model.transform * face.transform; vertexData.positions[0] = transformed * glm::vec4(0, 0, 0, 1); @@ -131,6 +131,248 @@ void AddFacesByBlockModel(RendererSectionData& data, const BlockFaces& model, co } } +void AddLiquidFacesByBlockModel(RendererSectionData& data, const BlockId& blockId, const BlockFaces& model, const glm::mat4& transform, bool visibility[FaceDirection::none], const Vector& pos, const SectionsData& sections, bool smoothLighting) { + const ParsedFace& flowData = model.faces[0]; + const ParsedFace& stillData = model.faces[1]; + size_t addedFaces = 0; + + constexpr float highLevel = 0.9f; + constexpr float lowLevel = 0.05f; + + constexpr float neighborLevels[] = { + lowLevel + ((highLevel - lowLevel) / 7) * 7.0f, + lowLevel + ((highLevel - lowLevel) / 7) * 6.0f, + lowLevel + ((highLevel - lowLevel) / 7) * 5.0f, + lowLevel + ((highLevel - lowLevel) / 7) * 4.0f, + lowLevel + ((highLevel - lowLevel) / 7) * 3.0f, + lowLevel + ((highLevel - lowLevel) / 7) * 2.0f, + lowLevel + ((highLevel - lowLevel) / 7) * 1.0f, + lowLevel + ((highLevel - lowLevel) / 7) * 0.0f, + }; + + uint8_t neighborsLiquids[FaceDirection::none + 1] = { 0 }; + for (size_t i = 0; i < FaceDirection::none; i++) { + const BlockId bid = sections.GetBlockId(pos + FaceDirectionVector[i]); + neighborsLiquids[i] = bid.id == blockId.id ? bid.state & 0b00000111 : 0; + } + neighborsLiquids[FaceDirection::none] = blockId.state & 0b00000111; + + const bool liquidFalling = blockId.state & 0x8; + if (liquidFalling) { + if (!neighborsLiquids[FaceDirection::down]) { + addedFaces++; + VertexData& vertex = data.liquidVertices.emplace_back(); + vertex.positions[0] = transform * glm::vec4(0, 0, 0, 1); + vertex.positions[1] = transform * glm::vec4(1, 0, 0, 1); + vertex.positions[2] = transform * glm::vec4(1, 0, 1, 1); + vertex.positions[3] = transform * glm::vec4(0, 0, 1, 1); + } + + if (!neighborsLiquids[FaceDirection::up]) { + addedFaces++; + VertexData& vertex = data.liquidVertices.emplace_back(); + vertex.positions[0] = transform * glm::vec4(0, 1, 0, 1); + vertex.positions[1] = transform * glm::vec4(0, 1, 1, 1); + vertex.positions[2] = transform * glm::vec4(1, 1, 1, 1); + vertex.positions[3] = transform * glm::vec4(1, 1, 0, 1); + } + + if (!neighborsLiquids[FaceDirection::north]) { + addedFaces++; + VertexData& vertex = data.liquidVertices.emplace_back(); + vertex.positions[0] = transform * glm::vec4(1, 0, 0, 1); + vertex.positions[1] = transform * glm::vec4(0, 0, 0, 1); + vertex.positions[2] = transform * glm::vec4(0, 1, 0, 1); + vertex.positions[3] = transform * glm::vec4(1, 1, 0, 1); + } + + if (!neighborsLiquids[FaceDirection::south]) { + addedFaces++; + VertexData& vertex = data.liquidVertices.emplace_back(); + vertex.positions[0] = transform * glm::vec4(0, 0, 1, 1); + vertex.positions[1] = transform * glm::vec4(1, 0, 1, 1); + vertex.positions[2] = transform * glm::vec4(1, 1, 1, 1); + vertex.positions[3] = transform * glm::vec4(0, 1, 1, 1); + } + + if (!neighborsLiquids[FaceDirection::west]) { + addedFaces++; + VertexData& vertex = data.liquidVertices.emplace_back(); + vertex.positions[0] = transform * glm::vec4(0, 0, 0, 1); + vertex.positions[1] = transform * glm::vec4(0, 0, 1, 1); + vertex.positions[2] = transform * glm::vec4(0, 1, 1, 1); + vertex.positions[3] = transform * glm::vec4(0, 1, 0, 1); + } + + if (!neighborsLiquids[FaceDirection::east]) { + addedFaces++; + VertexData& vertex = data.liquidVertices.emplace_back(); + vertex.positions[0] = transform * glm::vec4(1, 0, 1, 1); + vertex.positions[1] = transform * glm::vec4(1, 0, 0, 1); + vertex.positions[2] = transform * glm::vec4(1, 1, 0, 1); + vertex.positions[3] = transform * glm::vec4(1, 1, 1, 1); + } + } + else { + const float bLevel = neighborLevels[neighborsLiquids[FaceDirection::none]]; + const float nLevel = neighborLevels[neighborsLiquids[FaceDirection::north]]; + const float eLevel = neighborLevels[neighborsLiquids[FaceDirection::east]]; + const float sLevel = neighborLevels[neighborsLiquids[FaceDirection::south]]; + const float wLevel = neighborLevels[neighborsLiquids[FaceDirection::west]]; + const float nwLevel = neighborLevels[neighborsLiquids[FaceDirection::northWest]]; + const float neLevel = neighborLevels[neighborsLiquids[FaceDirection::northEast]]; + const float swLevel = neighborLevels[neighborsLiquids[FaceDirection::southWest]]; + const float seLevel = neighborLevels[neighborsLiquids[FaceDirection::southEast]]; + + const glm::vec4 nwCorner = glm::vec4(0, _min(nLevel, wLevel, nwLevel, bLevel), 0, 1); + const glm::vec4 neCorner = glm::vec4(1, _min(nLevel, eLevel, neLevel, bLevel), 0, 1); + const glm::vec4 swCorner = glm::vec4(0, _min(sLevel, wLevel, swLevel, bLevel), 1, 1); + const glm::vec4 seCorner = glm::vec4(1, _min(sLevel, eLevel, seLevel, bLevel), 1, 1); + + if (!neighborsLiquids[FaceDirection::down]) { + addedFaces++; + VertexData& vertex = data.liquidVertices.emplace_back(); + vertex.positions[0] = transform * glm::vec4(0, 0, 0, 1); + vertex.positions[1] = transform * glm::vec4(1, 0, 0, 1); + vertex.positions[2] = transform * glm::vec4(1, 0, 1, 1); + vertex.positions[3] = transform * glm::vec4(0, 0, 1, 1); + } + + if (!neighborsLiquids[FaceDirection::up]) { + addedFaces++; + + FaceDirection flowDirection = FaceDirection::north; + if (nwCorner.y + swCorner.y > neCorner.y + seCorner.y) + flowDirection = FaceDirection::east; + else if (neCorner.y + seCorner.y > nwCorner.y + swCorner.y) + flowDirection = FaceDirection::west; + else if (nwCorner.y + neCorner.y > swCorner.y + seCorner.y) + flowDirection = FaceDirection::south; + else + flowDirection = FaceDirection::north; + + glm::mat4 flowMat = glm::mat4(1.0f); + + switch (flowDirection) + { + case FaceDirection::east: + break; + case FaceDirection::west: + break; + case FaceDirection::south: + break; + case FaceDirection::north: + break; + default: + break; + } + + VertexData& vertex = data.liquidVertices.emplace_back(); + vertex.positions[0] = transform * flowMat * nwCorner; + vertex.positions[1] = transform * flowMat * swCorner; + vertex.positions[2] = transform * flowMat * seCorner; + vertex.positions[3] = transform * flowMat * neCorner; + + const ParsedFace &texData = + _max(nwCorner.y, swCorner.y, seCorner.y, neCorner.y) == + _min(nwCorner.y, swCorner.y, seCorner.y, neCorner.y) ? + stillData : flowData; + + vertex.uvs[0] = TransformTextureCoord(texData.texture, glm::vec2(0, 0), texData.frames); + vertex.uvs[1] = TransformTextureCoord(texData.texture, glm::vec2(1, 0), texData.frames); + vertex.uvs[2] = TransformTextureCoord(texData.texture, glm::vec2(1, 1), texData.frames); + vertex.uvs[3] = TransformTextureCoord(texData.texture, glm::vec2(0, 1), texData.frames); + + vertex.layerAnimationAo.r = texData.layer; + vertex.layerAnimationAo.g = texData.frames; + + glm::vec3 normal = glm::cross(vertex.positions[1] - vertex.positions[0], vertex.positions[3] - vertex.positions[0]); + vertex.normal = glm::normalize(normal); + } + + if (!neighborsLiquids[FaceDirection::north]) { + addedFaces++; + VertexData& vertex = data.liquidVertices.emplace_back(); + vertex.positions[0] = transform * glm::vec4(1, 0, 0, 1); + vertex.positions[1] = transform * glm::vec4(0, 0, 0, 1); + vertex.positions[2] = transform * nwCorner; + vertex.positions[3] = transform * neCorner; + } + + if (!neighborsLiquids[FaceDirection::south]) { + addedFaces++; + VertexData& vertex = data.liquidVertices.emplace_back(); + vertex.positions[0] = transform * glm::vec4(0, 0, 1, 1); + vertex.positions[1] = transform * glm::vec4(1, 0, 1, 1); + vertex.positions[2] = transform * seCorner; + vertex.positions[3] = transform * swCorner; + } + + if (!neighborsLiquids[FaceDirection::west]) { + addedFaces++; + VertexData& vertex = data.liquidVertices.emplace_back(); + vertex.positions[0] = transform * glm::vec4(0, 0, 0, 1); + vertex.positions[1] = transform * glm::vec4(0, 0, 1, 1); + vertex.positions[2] = transform * swCorner; + vertex.positions[3] = transform * nwCorner; + } + + if (!neighborsLiquids[FaceDirection::east]) { + addedFaces++; + VertexData& vertex = data.liquidVertices.emplace_back(); + vertex.positions[0] = transform * glm::vec4(1, 0, 1, 1); + vertex.positions[1] = transform * glm::vec4(1, 0, 0, 1); + vertex.positions[2] = transform * neCorner; + vertex.positions[3] = transform * seCorner; + } + } + + + glm::vec3 absPos = (sections.data[1][1][1].GetPosition() * 16).glm(); + BlockLightness light = sections.GetLight(pos); + BlockLightness skyLight = sections.GetSkyLight(pos); + glm::vec2 lightness; + lightness.x = light.self; + lightness.y = skyLight.self; + for (size_t i = data.liquidVertices.size() - addedFaces; i < data.liquidVertices.size(); i++) { + VertexData& vertex = data.liquidVertices[i]; + + if (glm::length(vertex.normal) < 0.5f) { + vertex.uvs[0] = TransformTextureCoord(flowData.texture, glm::vec2(0, 0), flowData.frames); + vertex.uvs[1] = TransformTextureCoord(flowData.texture, glm::vec2(1, 0), flowData.frames); + vertex.uvs[2] = TransformTextureCoord(flowData.texture, glm::vec2(1, 1), flowData.frames); + vertex.uvs[3] = TransformTextureCoord(flowData.texture, glm::vec2(0, 1), flowData.frames); + + glm::vec3 normal = glm::cross(vertex.positions[1] - vertex.positions[0], vertex.positions[3] - vertex.positions[0]); + vertex.normal = glm::normalize(normal); + + vertex.layerAnimationAo.r = flowData.layer; + vertex.layerAnimationAo.g = flowData.frames; + } + + vertex.layerAnimationAo.b = 0.0f; + vertex.colors = glm::vec3(1.0f); + + if (smoothLighting) { + for (size_t i = 0; i < 4; i++) { + glm::vec3 baseLightPos = vertex.positions[i] - absPos; + glm::vec3 lightPos = baseLightPos + vertex.normal * 0.5f; + glm::ivec3 basePos = glm::trunc(lightPos); + BlockLightness light = sections.GetLight(Vector(basePos.x, basePos.y, basePos.z)); + BlockLightness skyLight = sections.GetSkyLight(Vector(basePos.x, basePos.y, basePos.z)); + vertex.lights[i].x = InterpolateBlockLightness(light, lightPos - glm::vec3(basePos)); + vertex.lights[i].y = InterpolateBlockLightness(skyLight, lightPos - glm::vec3(basePos)); + } + } + else { + vertex.lights[0] = lightness; + vertex.lights[1] = lightness; + vertex.lights[2] = lightness; + vertex.lights[3] = lightness; + } + } +} + BlockFaces *GetInternalBlockModel(const BlockId& id, std::vector<std::pair<BlockId, BlockFaces*>> &idModels) { for (const auto& it : idModels) { if (it.first == id) @@ -213,11 +455,16 @@ RendererSectionData ParseSection(const SectionsData §ions, bool smoothLighti transform = glm::translate(baseOffset, vec.glm()); BlockFaces *model = GetInternalBlockModel(block, idModels); - AddFacesByBlockModel(data, *model, transform, blockVisibility[y * 256 + z * 16 + x], vec, sections, smoothLighting); + if (model->isLiquid) + AddLiquidFacesByBlockModel(data, block, *model, transform, blockVisibility[y * 256 + z * 16 + x], vec, sections, smoothLighting); + else + AddFacesByBlockModel(data, *model, transform, blockVisibility[y * 256 + z * 16 + x], vec, sections, smoothLighting); } } } - data.vertices.shrink_to_fit(); + + data.solidVertices.shrink_to_fit(); + data.liquidVertices.shrink_to_fit(); return data; } diff --git a/src/RendererSectionData.hpp b/src/RendererSectionData.hpp index 0f9ade6..ac69bff 100644 --- a/src/RendererSectionData.hpp +++ b/src/RendererSectionData.hpp @@ -68,7 +68,8 @@ struct VertexData { }; struct RendererSectionData { - std::vector<VertexData> vertices; + std::vector<VertexData> solidVertices; + std::vector<VertexData> liquidVertices; size_t hash = 0; Vector sectionPos; bool forced = false; diff --git a/src/RendererWorld.cpp b/src/RendererWorld.cpp index af177d7..26c1f69 100644 --- a/src/RendererWorld.cpp +++ b/src/RendererWorld.cpp @@ -189,7 +189,7 @@ RendererWorld::RendererWorld(std::shared_ptr<Gal::Framebuffer> target, bool deff } it->second.UpdateData(parsing[id].renderer); } else - sections.emplace(std::make_pair(parsing[id].renderer.sectionPos, RendererSection(parsing[id].renderer, sectionsPipeline, sectionsBufferBinding))); + sections.emplace(std::make_pair(parsing[id].renderer.sectionPos, RendererSection(parsing[id].renderer, solidSectionsPipeline, solidSectionsBufferBinding, liquidSectionsPipeline, liquidSectionsBufferBinding))); parsing[id] = RendererWorld::SectionParsing(); }); @@ -267,7 +267,8 @@ RendererWorld::RendererWorld(std::shared_ptr<Gal::Framebuffer> target, bool deff RendererWorld::~RendererWorld() { size_t faces = 0; for (auto& it : sections) { - faces += it.second.numOfFaces; + faces += it.second.GetSolidFacesCount(); + faces += it.second.GetLiquidFacesCount(); } LOG(INFO) << "Total faces to render: " << faces; isRunning = false; @@ -342,7 +343,6 @@ void RendererWorld::Render(float screenRatio) { auto rawGlobalTime = (std::chrono::high_resolution_clock::now() - globalTimeStart); float globalTime = rawGlobalTime.count() / 1000000000.0f; globalSpb->Get<GlobalShaderParameters>()->globalTime = globalTime; - sectionsPipeline->Activate(); Frustum frustum(projView); renderList.clear(); @@ -362,14 +362,20 @@ void RendererWorld::Render(float screenRatio) { continue; } renderList.push_back(section.first); - renderedFaces += section.second.numOfFaces; + renderedFaces += section.second.GetSolidFacesCount(); + renderedFaces += section.second.GetLiquidFacesCount(); } glm::vec3 playerChunk(GetGameState()->GetPlayer()->pos / 16); std::sort(renderList.begin(), renderList.end(), [playerChunk](const Vector& lhs, const Vector& rhs) { return glm::distance2(lhs.glm(), playerChunk) < glm::distance2(rhs.glm(), playerChunk); }); + solidSectionsPipeline->Activate(); for (const auto& renderPos : renderList) { - sections.at(renderPos).Render(); + sections.at(renderPos).RenderSolid(); + } + liquidSectionsPipeline->Activate(); + for (const auto& renderPos : renderList) { + sections.at(renderPos).RenderLiquid(); } DebugInfo::culledSections = culledSections; DebugInfo::renderFaces = renderedFaces; @@ -418,14 +424,24 @@ void RendererWorld::Render(float screenRatio) { } void RendererWorld::PrepareRender(std::shared_ptr<Gal::Framebuffer> target, bool defferedShading) { - std::string sectionVertexSource, sectionPixelSource; + std::string solidSectionVertexSource, solidSectionPixelSource; { auto vertAsset = AssetManager::GetAssetByAssetName("/altcraft/shaders/vert/face"); - sectionVertexSource = std::string((char*)vertAsset->data.data(), (char*)vertAsset->data.data() + vertAsset->data.size()); + solidSectionVertexSource = std::string((char*)vertAsset->data.data(), (char*)vertAsset->data.data() + vertAsset->data.size()); auto pixelAsset = defferedShading ? AssetManager::GetAssetByAssetName("/altcraft/shaders/frag/face") : AssetManager::GetAssetByAssetName("/altcraft/shaders/frag/fwd_face"); - sectionPixelSource = std::string((char*)pixelAsset->data.data(), (char*)pixelAsset->data.data() + pixelAsset->data.size()); + solidSectionPixelSource = std::string((char*)pixelAsset->data.data(), (char*)pixelAsset->data.data() + pixelAsset->data.size()); + } + + std::string liquidSectionVertexSource, liquidSectionPixelSource; + { + auto vertAsset = AssetManager::GetAssetByAssetName("/altcraft/shaders/vert/liquid_face"); + liquidSectionVertexSource = std::string((char*)vertAsset->data.data(), (char*)vertAsset->data.data() + vertAsset->data.size()); + + auto pixelAsset = defferedShading ? AssetManager::GetAssetByAssetName("/altcraft/shaders/frag/liquid_face") : + AssetManager::GetAssetByAssetName("/altcraft/shaders/frag/fwd_liquid_face"); + liquidSectionPixelSource = std::string((char*)pixelAsset->data.data(), (char*)pixelAsset->data.data() + pixelAsset->data.size()); } std::string entitiesVertexSource, entitiesPixelSource; @@ -450,13 +466,13 @@ void RendererWorld::PrepareRender(std::shared_ptr<Gal::Framebuffer> target, bool auto gal = Gal::GetImplementation(); { - auto sectionsPLC = gal->CreatePipelineConfig(); - sectionsPLC->SetTarget(target); - sectionsPLC->AddStaticTexture("textureAtlas", AssetManager::GetTextureAtlas()); - sectionsPLC->SetVertexShader(gal->LoadVertexShader(sectionVertexSource)); - sectionsPLC->SetPixelShader(gal->LoadPixelShader(sectionPixelSource)); - sectionsPLC->SetPrimitive(Gal::Primitive::TriangleFan); - sectionsBufferBinding = sectionsPLC->BindVertexBuffer({ + auto solidSectionPLC = gal->CreatePipelineConfig(); + solidSectionPLC->SetTarget(target); + solidSectionPLC->AddStaticTexture("textureAtlas", AssetManager::GetTextureAtlas()); + solidSectionPLC->SetVertexShader(gal->LoadVertexShader(solidSectionVertexSource)); + solidSectionPLC->SetPixelShader(gal->LoadPixelShader(solidSectionPixelSource)); + solidSectionPLC->SetPrimitive(Gal::Primitive::TriangleFan); + solidSectionsBufferBinding = solidSectionPLC->BindVertexBuffer({ {"pos", Gal::Type::Vec3, 4, 1}, {"uv", Gal::Type::Vec2, 4, 1}, {"light", Gal::Type::Vec2, 4, 1}, @@ -464,9 +480,28 @@ void RendererWorld::PrepareRender(std::shared_ptr<Gal::Framebuffer> target, bool {"color", Gal::Type::Vec3, 1, 1}, {"layerAnimationAo", Gal::Type::Vec3, 1, 1}, }); - sectionsPipeline = gal->BuildPipeline(sectionsPLC); + solidSectionsPipeline = gal->BuildPipeline(solidSectionPLC); } - + + { + auto liquidSectionPLC = gal->CreatePipelineConfig(); + liquidSectionPLC->SetTarget(target); + liquidSectionPLC->AddStaticTexture("textureAtlas", AssetManager::GetTextureAtlas()); + liquidSectionPLC->SetVertexShader(gal->LoadVertexShader(liquidSectionVertexSource)); + liquidSectionPLC->SetPixelShader(gal->LoadPixelShader(liquidSectionPixelSource)); + liquidSectionPLC->SetPrimitive(Gal::Primitive::TriangleFan); + liquidSectionPLC->SetBlending(Gal::Blending::Additive); + liquidSectionsBufferBinding = liquidSectionPLC->BindVertexBuffer({ + {"pos", Gal::Type::Vec3, 4, 1}, + {"uv", Gal::Type::Vec2, 4, 1}, + {"light", Gal::Type::Vec2, 4, 1}, + {"normal", Gal::Type::Vec3, 1, 1}, + {"color", Gal::Type::Vec3, 1, 1}, + {"layerAnimationAo", Gal::Type::Vec3, 1, 1}, + }); + liquidSectionsPipeline = gal->BuildPipeline(liquidSectionPLC); + } + { auto entitiesPLC = gal->CreatePipelineConfig(); entitiesPLC->SetTarget(target); diff --git a/src/RendererWorld.hpp b/src/RendererWorld.hpp index 438c022..13d9739 100644 --- a/src/RendererWorld.hpp +++ b/src/RendererWorld.hpp @@ -43,8 +43,10 @@ class RendererWorld { std::map<Vector, RendererSection> sections; void UpdateAllSections(VectorF playerPos); std::chrono::time_point<std::chrono::high_resolution_clock> globalTimeStart; - std::shared_ptr<Gal::Pipeline> sectionsPipeline; - std::shared_ptr<Gal::BufferBinding> sectionsBufferBinding; + std::shared_ptr<Gal::Pipeline> solidSectionsPipeline; + std::shared_ptr<Gal::BufferBinding> solidSectionsBufferBinding; + std::shared_ptr<Gal::Pipeline> liquidSectionsPipeline; + std::shared_ptr<Gal::BufferBinding> liquidSectionsBufferBinding; //Entities std::vector<RendererEntity> entities; std::shared_ptr<Gal::Pipeline> entitiesPipeline; |