From e8080bffb6061048017ceb51646037b7795e8677 Mon Sep 17 00:00:00 2001 From: Shu Date: Thu, 3 Dec 2020 19:46:47 +0100 Subject: [PATCH] Biplanar mapping --- TODO.md | 3 +- resource/content/shaders/Color.fs.spv | 2 +- resource/content/shaders/Color.vs.spv | 2 +- resource/content/shaders/Sky.fs.spv | 2 +- resource/content/shaders/Sky.vs.spv | 2 +- resource/content/shaders/Tris.fs.spv | 2 +- resource/content/shaders/Tris.vs.spv | 2 +- resource/content/shaders/Voxel.fs | 113 +++++++++++-- resource/content/shaders/Voxel.fs.spv | 4 +- resource/content/shaders/Voxel.geo.fs.spv | 4 +- resource/content/shaders/Voxel.geo.gs.spv | 2 +- resource/content/shaders/Voxel.geo.ins.fs.spv | 4 +- resource/content/shaders/Voxel.geo.ins.gs.spv | 2 +- resource/content/shaders/Voxel.geo.ins.vs.spv | 2 +- resource/content/shaders/Voxel.geo.vs.spv | 2 +- resource/content/shaders/Voxel.ins.fs.spv | 4 +- resource/content/shaders/Voxel.ins.vs.spv | 2 +- resource/content/shaders/Voxel.vs.spv | 2 +- resource/shaders-src/Voxel.frag | 107 ++++++++++-- resource/shaders-src/Voxel.vert | 4 +- src/client/config.hpp | 4 +- src/client/render/Renderer.hpp | 10 +- src/client/render/UI.cpp | 69 +++++++- src/client/render/gl/pass/VoxelProgram.cpp | 4 +- src/client/render/vk/Pipeline.cpp | 156 +++++++----------- 25 files changed, 351 insertions(+), 159 deletions(-) diff --git a/TODO.md b/TODO.md index 798f057..31b9c43 100644 --- a/TODO.md +++ b/TODO.md @@ -98,8 +98,7 @@ Released as `0.0.1`: `Pre alpha 1` - [ ] Merge stochastic and triplanar - https://assetstore.unity.com/packages/tools/terrain/microsplat-96478 - https://www.youtube.com/user/slipster216/videos - - [ ] Biplanar - - Stochastic + - [x] Biplanar - [ ] Distance resampling - [ ] Tesselation - [ ] Planet scale LOD (using chunk level average) diff --git a/resource/content/shaders/Color.fs.spv b/resource/content/shaders/Color.fs.spv index 1a8f64c..6da5431 100644 --- a/resource/content/shaders/Color.fs.spv +++ b/resource/content/shaders/Color.fs.spv @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fbd3f1dc76303d181564dbf54fc1833c874c14d6a911009b2192349f70613af2 +oid sha256:5dca0e5e1e75467738084e8e000f79fc1726e5130b1982c1df2ef99b5ab68f23 size 480 diff --git a/resource/content/shaders/Color.vs.spv b/resource/content/shaders/Color.vs.spv index 2342974..ce6bd11 100644 --- a/resource/content/shaders/Color.vs.spv +++ b/resource/content/shaders/Color.vs.spv @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:26a5bd8054a9172df79d6b18b899126f4c2ee2e3ddfb4b0d3ee776d5a5e375a8 +oid sha256:d279bc5d10c80dd8808d9030f2d0e1c7df424a3b0cd4645d79a5d6c2d6853985 size 1752 diff --git a/resource/content/shaders/Sky.fs.spv b/resource/content/shaders/Sky.fs.spv index f479c7f..79a1954 100644 --- a/resource/content/shaders/Sky.fs.spv +++ b/resource/content/shaders/Sky.fs.spv @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c253918a17daa10ef5a40d8e59436d7522a0b797de1ca009b13f0c3161ac2a53 +oid sha256:573936057f3ad42af38b3c0a0998b3476a70a7824c76a434604c2833fdc89a6b size 756 diff --git a/resource/content/shaders/Sky.vs.spv b/resource/content/shaders/Sky.vs.spv index 51f48c3..6b24695 100644 --- a/resource/content/shaders/Sky.vs.spv +++ b/resource/content/shaders/Sky.vs.spv @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7f7f10a7284cd223038b64ec638bdf7151b250f2d9af78e6e4d4c4ae7f605d71 +oid sha256:876a3fe17fe4e8382845bbf39191acae6b187af9d44bebf6169a011b8af1e029 size 1664 diff --git a/resource/content/shaders/Tris.fs.spv b/resource/content/shaders/Tris.fs.spv index a103cb7..85fb916 100644 --- a/resource/content/shaders/Tris.fs.spv +++ b/resource/content/shaders/Tris.fs.spv @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4b32ce588c35a63f6b6ff88860385d1afca26ba07270ce602b0fd55db589e619 +oid sha256:41d26b988479e55b6a511fe6cc755c3db5e8e28692abb783d43e1b00dec6ad65 size 764 diff --git a/resource/content/shaders/Tris.vs.spv b/resource/content/shaders/Tris.vs.spv index 53b98d3..68e9761 100644 --- a/resource/content/shaders/Tris.vs.spv +++ b/resource/content/shaders/Tris.vs.spv @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fe04f5d315d7c0d40464a7de6f6ad7300da9f51331d2e938c6d14cf6c1810bbd +oid sha256:bd4c7adf5fae8e647d90e757e9cac9763c85a64c10c616b29adddc8f2bdd8017 size 1972 diff --git a/resource/content/shaders/Voxel.fs b/resource/content/shaders/Voxel.fs index 62e01bd..10a1872 100644 --- a/resource/content/shaders/Voxel.fs +++ b/resource/content/shaders/Voxel.fs @@ -45,7 +45,7 @@ vec2 hash2D(vec2 s) { return fract(sin(mod(vec2(dot(s, vec2(127.1, 311.7)), dot(s, vec2(269.5, 183.3))), 3.14159)) * 43758.5453); } -vec4 textureStochastic(sampler2DArray sample, vec3 UV) { +vec4 textureStochasticGrad(sampler2DArray sample, vec3 UV, vec2 dx, vec2 dy) { #ifdef STOCHASTIC // triangular by approx 2*sqrt(3) vec2 skewUV = mat2(1.0, 0.0, -0.57735027, 1.15470054) * (UV.xy * 3.46400); @@ -72,12 +72,16 @@ vec4 textureStochastic(sampler2DArray sample, vec3 UV) { BW_vx3 = vec3(-barry.z, 1.0 - barry.y, 1.0 - barry.x); } - vec2 dx = dFdx(UV.xy); - vec2 dy = dFdy(UV.xy); - return textureGrad(sample, vec3(UV.xy + hash2D(BW_vx0.xy), UV.z), dx, dy) * BW_vx3.x + textureGrad(sample, vec3(UV.xy + hash2D(BW_vx1.xy), UV.z), dx, dy) * BW_vx3.y + textureGrad(sample, vec3(UV.xy + hash2D(BW_vx2.xy), UV.z), dx, dy) * BW_vx3.z; +#else + return textureGrad(sample, UV, dx, dy); +#endif +} +vec4 textureStochastic(sampler2DArray sample, vec3 UV) { +#ifdef STOCHASTIC + return textureStochasticGrad(sample, UV, dFdx(UV.xy), dFdy(UV.xy)); #else return texture(sample, UV); #endif @@ -106,23 +110,54 @@ vec4 getTexture(sampler2DArray sample, vec2 UV) { return textureStochastic(sample, vec3(UV, vs.Texture)); #endif } +vec4 getTextureGrad(sampler2DArray sample, vec2 UV, vec2 dx, vec2 dy) { +#ifdef GEOMETRY +#ifdef BLEND + vec4 colx = textureStochasticGrad(sample, vec3(UV, vs.Textures[0]), dx, dy); + if(vs.Textures[1] == vs.Textures[0]) { + return vs.Textures[2] == vs.Textures[0] ? colx : + mix(colx, textureStochasticGrad(sample, vec3(UV, vs.Textures[2]), dx, dy), vs.TextureRatio.z); + } else { + vec4 coly = textureStochasticGrad(sample, vec3(UV, vs.Textures[1]), dx, dy); + return vs.Textures[2] == vs.Textures[0] ? mix(colx, coly, vs.TextureRatio.y) : ( + vs.Textures[2] == vs.Textures[1] ? mix(coly, colx, vs.TextureRatio.x) : + colx * vs.TextureRatio.x + coly * vs.TextureRatio.y + textureStochasticGrad(sample, vec3(UV, vs.Textures[2]), dx, dy) * vs.TextureRatio.z); + } +#else + int mainTexture = vs.TextureRatio.x >= vs.TextureRatio.y ? + (vs.TextureRatio.x >= vs.TextureRatio.z ? 0 : 2) : + (vs.TextureRatio.y >= vs.TextureRatio.z ? 1 : 2); + return textureStochasticGrad(sample, vec3(UV, vs.Textures[mainTexture]), dx, dy); +#endif +#else + return textureStochasticGrad(sample, vec3(UV, vs.Texture), dx, dy); +#endif +} -vec4 getTriTexture(sampler2DArray sample, vec2 crdx, vec2 crdy, vec2 crdz, vec3 weights) { - return getTexture(sample, crdx) * weights.x + - getTexture(sample, crdy) * weights.y + - getTexture(sample, crdz) * weights.z; +vec4 getTriTexture(sampler2DArray sample, vec2 UVx, vec2 UVy, vec2 UVz, vec3 w) { + vec4 x = getTexture(sample, UVx); + vec4 y = getTexture(sample, UVy); + vec4 z = getTexture(sample, UVz); + return x*w.x + y*w.y + z*w.z; +} + +vec4 getBiTexture(sampler2DArray sample, vec2 UVa, vec2 UVb, vec2 dxa, vec2 dxb, vec2 dya, vec2 dyb, vec2 w) { + vec4 x = getTextureGrad(sample, UVa, dxa, dya); + vec4 y = getTextureGrad(sample, UVb, dxb, dyb); + return x*w.x + y*w.y; } void main() { float texScale = 1. / UNIT_SIZE; + float transitionSpeed = 2; #ifdef TRIPLANAR // Triplanar float plateauSize = 0.001; - float transitionSpeed = 2; vec3 blendWeights = abs(vs.FaceNormal_modelspace); blendWeights = blendWeights - plateauSize; - blendWeights = normalize(pow(max(blendWeights, 0), vec3(transitionSpeed))); + blendWeights = pow(max(blendWeights, 0), vec3(transitionSpeed)); + blendWeights = blendWeights / (blendWeights.x + blendWeights.y + blendWeights.z); vec2 UVx = vs.Position_modelspace.yz * texScale; vec2 UVy = vs.Position_modelspace.zx * texScale; vec2 UVz = vs.Position_modelspace.xy * texScale; @@ -143,6 +178,54 @@ void main() { vec3 texHOS = getTriTexture(HOSAtlas, UVx, UVy, UVz, blendWeights).rgb; #endif +#else +#ifdef BIPLANAR + // Biplanar + vec3 pos = vs.Position_modelspace * texScale; + vec3 dpdx = dFdx(pos); + vec3 dpdy = dFdy(pos); + vec3 blendWeights = abs(normalize(vs.FaceNormal_modelspace)); + + // determine major axis (in x; yz are following axis) + ivec3 ma = (blendWeights.x>blendWeights.y && blendWeights.x>blendWeights.z) ? ivec3(0,1,2) : + (blendWeights.y>blendWeights.z) ? ivec3(1,2,0) : ivec3(2,0,1); + // determine minor axis (in x; yz are following axis) + ivec3 mi = (blendWeights.x= vs.TextureRatio.y ? + (vs.TextureRatio.x >= vs.TextureRatio.z ? 0 : 2) : + (vs.TextureRatio.y >= vs.TextureRatio.z ? 1 : 2); + return textureStochasticGrad(smpl, vec3(UV, vs.Textures[mainTexture]), dx, dy); +} +#else + return textureStochasticGrad(smpl, vec3(UV, vs.Texture), dx, dy); +#endif +} -vec4 getTriTexture(sampler2DArray smpl, vec2 crdx, vec2 crdy, vec2 crdz, vec3 weights) { - return getTexture(smpl, crdx) * weights.x + - getTexture(smpl, crdy) * weights.y + - getTexture(smpl, crdz) * weights.z; +vec4 getTriTexture(sampler2DArray smpl, vec2 UVx, vec2 UVy, vec2 UVz, vec3 w) { + vec4 x = getTexture(smpl, UVx); + vec4 y = getTexture(smpl, UVy); + vec4 z = getTexture(smpl, UVz); + return x*w.x + y*w.y + z*w.z; +} + +vec4 getBiTexture(sampler2DArray smpl, vec2 UVa, vec2 UVb, vec2 dxa, vec2 dxb, vec2 dya, vec2 dyb, vec2 w) { + vec4 x = getTextureGrad(smpl, UVa, dxa, dya); + vec4 y = getTextureGrad(smpl, UVb, dxb, dyb); + return x*w.x + y*w.y; } void main() { float texScale = 1. / UNIT_SIZE; + float transitionSpeed = 2; vec4 tex; vec3 worldNormal, texHOS; if(TRIPLANAR) { // Triplanar float plateauSize = 0.001; - float transitionSpeed = 2; vec3 blendWeights = abs(vs.FaceNormal_modelspace); blendWeights = blendWeights - plateauSize; blendWeights = pow(max(blendWeights, 0), vec3(transitionSpeed)); + blendWeights = blendWeights / (blendWeights.x + blendWeights.y + blendWeights.z); vec2 UVx = vs.Position_modelspace.yz * texScale; vec2 UVy = vs.Position_modelspace.zx * texScale; vec2 UVz = vs.Position_modelspace.xy * texScale; @@ -155,6 +191,53 @@ if(PBR) { texHOS = getTriTexture(HOSAtlas, UVx, UVy, UVz, blendWeights).rgb; } +} else if(BIPLANAR) { + // Biplanar + vec3 pos = vs.Position_modelspace * texScale; + vec3 dpdx = dFdx(pos); + vec3 dpdy = dFdy(pos); + vec3 blendWeights = abs(normalize(vs.FaceNormal_modelspace)); + + // determine major axis (in x; yz are following axis) + ivec3 ma = (blendWeights.x>blendWeights.y && blendWeights.x>blendWeights.z) ? ivec3(0,1,2) : + (blendWeights.y>blendWeights.z) ? ivec3(1,2,0) : ivec3(2,0,1); + // determine minor axis (in x; yz are following axis) + ivec3 mi = (blendWeights.x(config["render"]["planar"].value_or(static_cast(renderer.voxel.planar))); renderer.voxel.stochastic = config["render"]["stochastic"].value_or(renderer.voxel.stochastic); renderer.voxel.geometry = config["render"]["geometry"].value_or(renderer.voxel.geometry); renderer.voxel.blend = config["render"]["blend"].value_or(renderer.voxel.blend); @@ -120,7 +120,7 @@ public: {"texture_quality", renderer.textureQuality}, {"texture_angular_quality", renderer.textureSharpness}, {"pbr", renderer.voxel.pbr}, - {"triplanar", renderer.voxel.triplanar}, + {"planar", static_cast(renderer.voxel.planar)}, {"stochastic", renderer.voxel.stochastic}, {"geometry", renderer.voxel.geometry}, {"blend", renderer.voxel.blend}, diff --git a/src/client/render/Renderer.hpp b/src/client/render/Renderer.hpp index 638921b..af1531f 100644 --- a/src/client/render/Renderer.hpp +++ b/src/client/render/Renderer.hpp @@ -15,12 +15,18 @@ namespace render { class Model; class LodModel; +enum class Planar { + Cheap = 1, + Biplanar = 2, + Triplanar = 3 +}; + /// Pass options struct passOptions { /// Apply light properties bool pbr = true; - /// Triplanar texture mapping - bool triplanar = false; + /// Texture mapping + Planar planar = Planar::Cheap; /// Transform texture UV bool stochastic = false; /// Active geometry pass diff --git a/src/client/render/UI.cpp b/src/client/render/UI.cpp index abfa6e9..11ef5d6 100644 --- a/src/client/render/UI.cpp +++ b/src/client/render/UI.cpp @@ -16,7 +16,67 @@ UI::UI() { // Setup Dear ImGui context IMGUI_CHECKVERSION(); ImGui::CreateContext(); - ImGui::StyleColorsDark(); + { + ImGui::StyleColorsDark(); + ImGuiStyle &style = ImGui::GetStyle(); + style.TabRounding = 1; + style.WindowRounding = 2; + style.GrabRounding = 2; + style.FrameRounding = 4; + style.ScrollbarRounding = 4; + style.WindowMenuButtonPosition = ImGuiDir_Right; + + // Purple dark theme + /*ImVec4* colors = style.Colors; + colors[ImGuiCol_Text] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f); + colors[ImGuiCol_TextDisabled] = ImVec4(0.56f, 0.56f, 0.56f, 1.00f); + colors[ImGuiCol_WindowBg] = ImVec4(0.06f, 0.06f, 0.06f, 0.94f); + colors[ImGuiCol_ChildBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); + colors[ImGuiCol_PopupBg] = ImVec4(0.08f, 0.08f, 0.08f, 0.94f); + colors[ImGuiCol_Border] = ImVec4(0.53f, 0.46f, 0.54f, 0.50f); + colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); + colors[ImGuiCol_FrameBg] = ImVec4(0.38f, 0.34f, 0.40f, 0.54f); + colors[ImGuiCol_FrameBgHovered] = ImVec4(0.83f, 0.26f, 0.98f, 0.40f); + colors[ImGuiCol_FrameBgActive] = ImVec4(0.73f, 0.26f, 0.98f, 0.67f); + colors[ImGuiCol_TitleBg] = ImVec4(0.14f, 0.00f, 0.21f, 1.00f); + colors[ImGuiCol_TitleBgActive] = ImVec4(0.39f, 0.16f, 0.48f, 1.00f); + colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.13f, 0.00f, 0.21f, 0.51f); + colors[ImGuiCol_MenuBarBg] = ImVec4(0.06f, 0.06f, 0.06f, 0.94f); + colors[ImGuiCol_ScrollbarBg] = ImVec4(0.02f, 0.02f, 0.02f, 0.53f); + colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.31f, 0.31f, 0.31f, 1.00f); + colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.41f, 0.41f, 0.41f, 1.00f); + colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.51f, 0.51f, 0.51f, 1.00f); + colors[ImGuiCol_CheckMark] = ImVec4(0.74f, 0.27f, 0.83f, 1.00f); + colors[ImGuiCol_SliderGrab] = ImVec4(0.55f, 0.21f, 0.80f, 1.00f); + colors[ImGuiCol_SliderGrabActive] = ImVec4(0.75f, 0.27f, 0.83f, 1.00f); + colors[ImGuiCol_Button] = ImVec4(0.85f, 0.26f, 0.98f, 0.40f); + colors[ImGuiCol_ButtonHovered] = ImVec4(0.76f, 0.26f, 0.98f, 1.00f); + colors[ImGuiCol_ButtonActive] = ImVec4(0.63f, 0.06f, 0.98f, 1.00f); + colors[ImGuiCol_Header] = ImVec4(0.81f, 0.26f, 0.98f, 0.31f); + colors[ImGuiCol_HeaderHovered] = ImVec4(0.84f, 0.26f, 0.98f, 0.80f); + colors[ImGuiCol_HeaderActive] = ImVec4(0.79f, 0.26f, 0.98f, 1.00f); + colors[ImGuiCol_Separator] = ImVec4(0.38f, 0.35f, 0.40f, 0.54f); + colors[ImGuiCol_SeparatorHovered] = ImVec4(0.64f, 0.10f, 0.75f, 0.78f); + colors[ImGuiCol_SeparatorActive] = ImVec4(0.53f, 0.10f, 0.75f, 1.00f); + colors[ImGuiCol_ResizeGrip] = ImVec4(0.77f, 0.26f, 0.98f, 0.25f); + colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.83f, 0.26f, 0.98f, 0.67f); + colors[ImGuiCol_ResizeGripActive] = ImVec4(0.76f, 0.26f, 0.98f, 0.95f); + colors[ImGuiCol_Tab] = ImVec4(0.48f, 0.18f, 0.58f, 0.86f); + colors[ImGuiCol_TabHovered] = ImVec4(0.79f, 0.26f, 0.98f, 0.80f); + colors[ImGuiCol_TabActive] = ImVec4(0.54f, 0.20f, 0.68f, 1.00f); + colors[ImGuiCol_TabUnfocused] = ImVec4(0.10f, 0.07f, 0.15f, 0.97f); + colors[ImGuiCol_TabUnfocusedActive] = ImVec4(0.22f, 0.14f, 0.42f, 1.00f); + colors[ImGuiCol_PlotLines] = ImVec4(0.61f, 0.61f, 0.61f, 1.00f); + colors[ImGuiCol_PlotLinesHovered] = ImVec4(1.00f, 0.43f, 0.35f, 1.00f); + colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f); + colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f); + colors[ImGuiCol_TextSelectedBg] = ImVec4(0.55f, 0.26f, 0.98f, 0.35f); + colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f); + colors[ImGuiCol_NavHighlight] = ImVec4(0.55f, 0.26f, 0.98f, 1.00f); + colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f); + colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.20f); + colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.35f);*/ + } for(auto file: std::filesystem::directory_iterator("content/textures/")) { if(file.is_directory() && file.path().filename() != "ui") @@ -87,10 +147,13 @@ UI::Actions UI::draw(config::client::options &options, state::state &state, cons { bool changeRenderer = false; + { + int planarIdx = static_cast(options.renderer.voxel.planar) - 1; + changeRenderer |= ImGui::Combo("Mapping", &planarIdx, "Cheap\0Biplanar\0Triplanar\0"); + options.renderer.voxel.planar = static_cast(planarIdx + 1); + } changeRenderer |= ImGui::Checkbox("PBR", &options.renderer.voxel.pbr); ImGui::SameLine(); - changeRenderer |= ImGui::Checkbox("Triplanar", &options.renderer.voxel.triplanar); - ImGui::SameLine(); changeRenderer |= ImGui::Checkbox("Stochastic", &options.renderer.voxel.stochastic); if (ImGui::IsItemHovered()) ImGui::SetTooltip("Hide textures tiling\nMay cause visible inconsistances on chunk borders"); diff --git a/src/client/render/gl/pass/VoxelProgram.cpp b/src/client/render/gl/pass/VoxelProgram.cpp index 08400bb..0899191 100644 --- a/src/client/render/gl/pass/VoxelProgram.cpp +++ b/src/client/render/gl/pass/VoxelProgram.cpp @@ -8,7 +8,9 @@ VoxelProgram::VoxelProgram(const VoxelProgram::options& opts, std::vector speIndex; + speData.fog = options.voxel.fog; + speIndex[0].constantID = 0; + speIndex[0].offset = offsetof(SpeData, fog); + speIndex[0].size = sizeof(SpeData::fog); + speData.pbr = options.voxel.pbr; + speIndex[1].constantID = 1; + speIndex[1].offset = offsetof(SpeData, pbr); + speIndex[1].size = sizeof(SpeData::pbr); + speData.biplanar = options.voxel.planar == render::Planar::Biplanar; + speIndex[2].constantID = 2; + speIndex[2].offset = offsetof(SpeData, biplanar); + speIndex[2].size = sizeof(SpeData::biplanar); + speData.triplanar = options.voxel.planar == render::Planar::Triplanar; + speIndex[3].constantID = 3; + speIndex[3].offset = offsetof(SpeData, triplanar); + speIndex[3].size = sizeof(SpeData::triplanar); + speData.stochastic = options.voxel.stochastic; + speIndex[4].constantID = 4; + speIndex[4].offset = offsetof(SpeData, stochastic); + speIndex[4].size = sizeof(SpeData::stochastic); + speData.blend = options.voxel.blend; + speIndex[5].constantID = 5; + speIndex[5].offset = offsetof(SpeData, blend); + speIndex[5].size = sizeof(SpeData::blend); + speData.curvature = options.voxel.curvature; + speIndex[6].constantID = 8; + speIndex[6].offset = offsetof(SpeData, curvature); + speIndex[6].size = sizeof(SpeData::curvature); + speData.curv_depth = options.voxel.curv_depth; + speIndex[7].constantID = 9; + speIndex[7].offset = offsetof(SpeData, curv_depth); + speIndex[7].size = sizeof(SpeData::curv_depth); + speData.unitSize = 8; //TODO: load from world.voxel_density + speIndex[8].constantID = 16; + speIndex[8].offset = offsetof(SpeData, unitSize); + speIndex[8].size = sizeof(SpeData::unitSize); + VkSpecializationInfo voxelSpecialization{}; + voxelSpecialization.dataSize = sizeof(SpeData); + voxelSpecialization.pData = &speData; + voxelSpecialization.mapEntryCount = speIndex.size(); + voxelSpecialization.pMapEntries = speIndex.data(); + { // World pipeline VkPushConstantRange pushRange{}; pushRange.offset = 0; @@ -391,57 +445,8 @@ Pipeline::Pipeline(VkDevice device, const PhysicalDeviceInfo &info, const render pushRange.stageFlags = VK_SHADER_STAGE_VERTEX_BIT; setLayout(worldPass, {voxelDescriptorSet}, {pushRange}); - struct SpeData { - bool fog; - bool pbr; - bool triplanar; - bool stochastic; - bool blend; - bool curvature; - bool curv_depth; - int32_t unitSize; - } speData; - std::array speIndex; - speData.fog = options.voxel.fog; - speIndex[0].constantID = 0; - speIndex[0].offset = offsetof(SpeData, fog); - speIndex[0].size = sizeof(SpeData::fog); - speData.pbr = options.voxel.pbr; - speIndex[1].constantID = 1; - speIndex[1].offset = offsetof(SpeData, pbr); - speIndex[1].size = sizeof(SpeData::pbr); - speData.triplanar = options.voxel.triplanar; - speIndex[2].constantID = 2; - speIndex[2].offset = offsetof(SpeData, triplanar); - speIndex[2].size = sizeof(SpeData::triplanar); - speData.stochastic = options.voxel.stochastic; - speIndex[3].constantID = 3; - speIndex[3].offset = offsetof(SpeData, stochastic); - speIndex[3].size = sizeof(SpeData::stochastic); - speData.blend = options.voxel.blend; - speIndex[4].constantID = 4; - speIndex[4].offset = offsetof(SpeData, blend); - speIndex[4].size = sizeof(SpeData::blend); - speData.curvature = options.voxel.curvature; - speIndex[5].constantID = 5; - speIndex[5].offset = offsetof(SpeData, curvature); - speIndex[5].size = sizeof(SpeData::curvature); - speData.curv_depth = options.voxel.curv_depth; - speIndex[6].constantID = 6; - speIndex[6].offset = offsetof(SpeData, curv_depth); - speIndex[6].size = sizeof(SpeData::curv_depth); - speData.unitSize = 8; //TODO: load from world.voxel_density - speIndex[7].constantID = 16; - speIndex[7].offset = offsetof(SpeData, unitSize); - speIndex[7].size = sizeof(SpeData::unitSize); - VkSpecializationInfo specialization{}; - specialization.dataSize = sizeof(SpeData); - specialization.pData = &speData; - specialization.mapEntryCount = speIndex.size(); - specialization.pMapEntries = speIndex.data(); - auto withGeometry = options.voxel.geometry && info.features.geometryShader; - auto shaderStages = setShaders(worldPass, withGeometry ? "Voxel.geo" : "Voxel", withGeometry, &specialization); + auto shaderStages = setShaders(worldPass, withGeometry ? "Voxel.geo" : "Voxel", withGeometry, &voxelSpecialization); VkPipelineVertexInputStateCreateInfo vertexInputInfo{}; vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; @@ -530,57 +535,8 @@ Pipeline::Pipeline(VkDevice device, const PhysicalDeviceInfo &info, const render pushRange.stageFlags = VK_SHADER_STAGE_VERTEX_BIT; setLayout(transparentWorldPass, {voxelDescriptorSet}, {pushRange}); - struct SpeData { - bool fog; - bool pbr; - bool triplanar; - bool stochastic; - bool blend; - bool curvature; - bool curv_depth; - int32_t unitSize; - } speData; - std::array speIndex; - speData.fog = options.voxel.fog; - speIndex[0].constantID = 0; - speIndex[0].offset = offsetof(SpeData, fog); - speIndex[0].size = sizeof(SpeData::fog); - speData.pbr = options.voxel.pbr; - speIndex[1].constantID = 1; - speIndex[1].offset = offsetof(SpeData, pbr); - speIndex[1].size = sizeof(SpeData::pbr); - speData.triplanar = options.voxel.triplanar; - speIndex[2].constantID = 2; - speIndex[2].offset = offsetof(SpeData, triplanar); - speIndex[2].size = sizeof(SpeData::triplanar); - speData.stochastic = options.voxel.stochastic; - speIndex[3].constantID = 3; - speIndex[3].offset = offsetof(SpeData, stochastic); - speIndex[3].size = sizeof(SpeData::stochastic); - speData.blend = options.voxel.blend; - speIndex[4].constantID = 4; - speIndex[4].offset = offsetof(SpeData, blend); - speIndex[4].size = sizeof(SpeData::blend); - speData.curvature = options.voxel.curvature; - speIndex[5].constantID = 5; - speIndex[5].offset = offsetof(SpeData, curvature); - speIndex[5].size = sizeof(SpeData::curvature); - speData.curv_depth = options.voxel.curv_depth; - speIndex[6].constantID = 6; - speIndex[6].offset = offsetof(SpeData, curv_depth); - speIndex[6].size = sizeof(SpeData::curv_depth); - speData.unitSize = 8; //TODO: load from world.voxel_density - speIndex[7].constantID = 16; - speIndex[7].offset = offsetof(SpeData, unitSize); - speIndex[7].size = sizeof(SpeData::unitSize); - VkSpecializationInfo specialization{}; - specialization.dataSize = sizeof(SpeData); - specialization.pData = &speData; - specialization.mapEntryCount = speIndex.size(); - specialization.pMapEntries = speIndex.data(); - auto withGeometry = options.voxel.geometry && info.features.geometryShader; - auto shaderStages = setShaders(transparentWorldPass, withGeometry ? "Voxel.geo" : "Voxel", withGeometry, &specialization); + auto shaderStages = setShaders(transparentWorldPass, withGeometry ? "Voxel.geo" : "Voxel", withGeometry, &voxelSpecialization); VkPipelineVertexInputStateCreateInfo vertexInputInfo{}; vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;