From a0b00b0f1c68a6784a9b10dc9e9426a11a02f276 Mon Sep 17 00:00:00 2001 From: Halbear Date: Sun, 20 Sep 2026 17:57:19 +0100 Subject: [PATCH] voxel biomes and CPU pushed blocks --- .../EngineResources/Texture/blueleaf_set.png | Bin 0 -> 4719 bytes .../Texture/blueleaf_set_2.png | Bin 0 -> 4009 bytes .../Texture/blueleaf_set_2_translucent.png | Bin 0 -> 3641 bytes .../Texture/blueleaf_set_translucent.png | Bin 0 -> 2013 bytes .../Texture/test_cube_translucency.png | Bin 0 -> 2219 bytes .../meshGenerationShared.glsl | 92 +++++++-- .../voxelGenerationShared.glsl | 77 ++++++-- .../shaders/packed_scene_fragment.glsl | 88 +++++++++ .../packed_scene_fragment_deferred.glsl | 149 ++++++++++++++ .../shaders/packed_scene_vertex.glsl | 24 +-- .../shaders/shadow_vertex_packed.glsl | 98 ++++++++- .../EngineResources/shaders/water_frag.glsl | 51 +++++ .../EngineResources/shaders/water_vert.glsl | 46 +++++ .../EngineCore/Display/VulkanRenderer.java | 187 ++++++++++++++++++ .../Terrain4J/EngineCore/Main/GameCore.java | 16 +- .../EngineCore/Main/PrimaryRuntime.java | 6 +- .../VoxelTerrainGeneration/Biome.java | 4 + .../SharedVoxelTerrainResources.java | 113 ++++++++++- .../VoxelTerrainGeneration/Voxel.java | 6 + .../VoxelChunkGenerator.java | 12 +- .../VoxelWorldManager.java | 116 +++++++++-- .../DeferredSceneRender.java | 6 +- .../Forward/ForwardSceneRender.java | 6 +- .../Vulkan/Structure/DeviceLayers/Device.java | 1 + 24 files changed, 1007 insertions(+), 91 deletions(-) create mode 100644 resources/EngineResources/Texture/blueleaf_set.png create mode 100644 resources/EngineResources/Texture/blueleaf_set_2.png create mode 100644 resources/EngineResources/Texture/blueleaf_set_2_translucent.png create mode 100644 resources/EngineResources/Texture/blueleaf_set_translucent.png create mode 100644 resources/EngineResources/Texture/test_cube_translucency.png create mode 100644 resources/EngineResources/shaders/packed_scene_fragment.glsl create mode 100644 resources/EngineResources/shaders/packed_scene_fragment_deferred.glsl create mode 100644 resources/EngineResources/shaders/water_frag.glsl create mode 100644 resources/EngineResources/shaders/water_vert.glsl create mode 100644 src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Computing/VoxelTerrainGeneration/Biome.java create mode 100644 src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Computing/VoxelTerrainGeneration/Voxel.java diff --git a/resources/EngineResources/Texture/blueleaf_set.png b/resources/EngineResources/Texture/blueleaf_set.png new file mode 100644 index 0000000000000000000000000000000000000000..3c22f594a1297516b3c88603c2653b00ec0a2975 GIT binary patch literal 4719 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 literal 0 HcmV?d00001 diff --git a/resources/EngineResources/Texture/blueleaf_set_2.png b/resources/EngineResources/Texture/blueleaf_set_2.png new file mode 100644 index 0000000000000000000000000000000000000000..7d4e30e4e3beaebfdeb9cc576856995241a2bfd5 GIT binary patch literal 4009 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 literal 0 HcmV?d00001 diff --git a/resources/EngineResources/Texture/blueleaf_set_2_translucent.png b/resources/EngineResources/Texture/blueleaf_set_2_translucent.png new file mode 100644 index 0000000000000000000000000000000000000000..c1b5625fb65c2e9245a260991299726721dd551c GIT binary patch literal 3641 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 LNkvXXu0mjfaH-f( literal 0 HcmV?d00001 diff --git a/resources/EngineResources/Texture/blueleaf_set_translucent.png b/resources/EngineResources/Texture/blueleaf_set_translucent.png new file mode 100644 index 0000000000000000000000000000000000000000..bf87761ece250c3ecdab25522d23b44ec634b9b0 GIT binary patch literal 2013 zcmV<32O{{1P)Px+mq|oHRCt`_n@>noT_49kzVD0AqPU8PGnk7AnuQfA2+o9U27&>F3}J*8IjyY7 zF$ew6R$T3Bd#|gdpq>%@qU*L1J8q64w|8J=r2#+;{QLx!gOA^GBa2 z&+|SXxXjF*bC2`;p5O1B-}z$|VDS&;KZpGT{z~TN=J@*cE9rEa(b3U@WvW#20QrMw zXJ-NM`FsGhwYAaP+gnjxi9~{QI!!vAw(BY+!oU8MU;ZbMNF?mm^7(x9_4Tp1xQNH& zVQFcpqPmusmuYBdz~}SXBFfi%lo0^n^5x3_bar;~?AbHAy1MxJ^C$E3^Mpd7vg?t8 z<%>`Vr9uEl7ywL9Puur3P21CrCCkgp0K9nd!ZuoZloU4~r3BD*9iPv~^z=0C?d^1S zcG_ah&d%CK6%)ZQ47)r)Utb?*&Yan^yiy@RuGKY7vpX+x#t0!?_X=Sc27bSviHQli zySwS`?&kFA(?y?AP5|lZ0ApigG&D3IgkWxNj+vR6qR;yMej z=re~N0)}C548yPt!>Fj9N(E466wow{NF-u^uBxiS@Ap?+ z&%(k2|I?s+4!!l|C0+j@&&v?{+l4@(>+apV2d*QLNLYzPLj4fPCm0M;TU$#o7(8%Y z>2#VzB2n-=${eg7W=z$jdxOP5~Yj)PS)4g$!4=`ZEcawW?5ffuec6f*BKida~WSq2xUS*5)1}8 zckUe7Y?ivZI{Wqg`}e$g^QNpioa=!?2s?Df#>QxDY;=`X(gU*DY|+nq5e|n5g+i{y zP=Mj#VE}I4yh$h&a;-5cCxC2aIUAI(rCMLtbpT?q7>kRGuC>77;bD9}AKl&E?Ck6i zi^c5n%7uVo7<6=W5Q#*%cI_HZpFU-3YKn!0g`%l(DwSe&b=BqiHBU4&AyOXJHsfkW1m9o~>)~vO)H7gtrTj6lnnwy)mbX~V}UAMyF zu(h_fW~EXo^;6+}=Joa^g>YVZhFgH8TnIRcL?TR0P3`;niHQmO{ne{i3zqr6-W&9K zy(P;iHwrkBd?gI`& ze}6wXyhsSa^XJchDW|jt?1zgNFVf%NkEUrHKYrZK0yRyuMRD?P;NI{5ndK3UMmc}} zJn!DUD_M4aexB{^Z8S|I7K^d6vI4;C*RK&m@Z-l1VzC&ROokIDPVo8jXHYo=WUA`* zdNED2=!U3VK+!bKW4+}yNVSTZy;#K_2qy>}>$M}-i0^5hAoX@bMug%E6PY!D0v?KJ^; zA4kvL+}zBiOP7ABQwot!PfyP;_YQp&a2jTsCSI=>P19&dC) zj`AQJdI%K4IRZ#Zb%KRRCX<+^x#vU(6+)m8qobqtC{R~dw=d%*r6xp&9s+wIJ4Q+z ziYkW3<0;q~I#E^t8S{TN$_n7@`1V6GnS`7d6hp~A0I)N;gRBUZa(`46Kpu9)aq{aR zNN*^FlEdKdL`e_$o&4hkP<9kJ2+nf>avrhQF(@p32l z%a#oR#$`)S2=m|q|2q9 z1Ofp&;d$`j0p#ro0NlQP8;{51S`t%2fJ`Q18#_2S$mHZCEF=UZP|s*xTDnZ*Q+_Hdm?f<)WkjlDBW)GBYz%@xRSVqzC#SXfxF-&abpR(JAWpASLwP}SM800000NkvXXu0mjfQ;N`{ literal 0 HcmV?d00001 diff --git a/resources/EngineResources/Texture/test_cube_translucency.png b/resources/EngineResources/Texture/test_cube_translucency.png new file mode 100644 index 0000000000000000000000000000000000000000..8c44307eb917b6c7eb0c0caf03f2be7f58a70eba GIT binary patch literal 2219 zcmV;c2vqlpP)Px-Wl2OqRCt`-S}|zb&KLgt=Qk88+U-=*Az-K=U=0Q@26ypfXvQ>ShfXCB+NDFl z;D)AT=+aUMp+g6Eiqj!O22Y&~=b_-?3-rGNz(*Y)S;rL?)VTCJG~a3E#z2;iJ2 z;B3R&_I{dTN-5Q9wN$IsnmWfa(&7!^GDx*rO~BvwzPT@i(B3CBT>&ABR~U{YD1^{P za2d!(2^oRro7b7Jw-NFm7A%}|wA*deYBhAbU9{V6D5a3g<-j>d7={zqc%Fw^tp?BY zAcQ~|h6uwDLI^#_ye^l^;g=15$=ceQz6TcVd2>y-Ax>UYN+mo_zoxed-h={IG9>RW zRSs}LoRl|>L&s^WfEfa|@^s!Dqu>8sH^gU27>3}SLkNLJqX7V@)oK8McDoG#*xlX5 zr%#_W^f3;dMx&u&Unmr?wzih|ZyMX&+ynr8{rVO7r9F<1kI`ziejP8v<|>3t_}kDY zL{R1@_`AZuOso_J2J#lKysOT)!@-_ot`KAdQ*k>CTp^;ATKp;i02><{fRVW=W9M=? z)M_=1Mk8!&Y+!eH7f+u)1pvH#`&Q4lvpi*Y5+Q_!zZnL(Tn-D*0RXguoO1xcix)4@ z?RKG*Lb+T{%>DfNGw$ENk3ylKb3m)r!twDjFji0qkuXRYhIsh!VQP+8cnH8)2B)>U zu3TY;fSu`KtN>=IY*mblS3Zl)Oor3OOhaKAmce;NDFq>f4uO8Zug{T~IiXM}0OPPw zO3j}G%vigMP`uA8{eC}D1DFch&)4tw^?qiha9aO8t1q9{+Fo@t;Z48OLcp3c-_50z zN=lh(0M}TS25>268)3$rY!Z;mFs?B=&dLC@ly@27k0(JXrH;Eejx+u5e!q_}40U|d zv6%#^Wj1qwIcF{pP(5yY#e}{c4z!kMfdJFP)oOKW?lDQ0%yIzdTq`yU_F2Q3p?XO&n($0*o;LKpe-3WsYEYbUslMF zQbI~O)%!vSaL$p>=M#i!CI(=Pfpb0)`<~}bl*-qU2YlbhU@(|ECk#V)o;NWsvtGc? z1xhJ|VTf+Gn`lNDWBQtIw>$6cwV3gpCggcD{^vG;t)S<5$mMbq$`Oa}8p}!sgTVxW zVvFZ_$#(`+4E#&d>-B(fZXgypP5wCpwA*d?zOP}<7{l$`w~^21fpNYtWhqF}ETq@# zK}v~Er-MqR0>&6RoenS~@&5IU5DewxI7X#XnNT>2BK-XM6E|+$(BVPy&me%jjj_Tv zZ{9?$R)dsM8zqioFvig9^-wGpfvgblyY$xY(rLCxDG>w#f*?Q?MTnvZ=jZ2;QsVsl z93MV>KomuZ`6QVnLC*Qq<;UdTE_42OMF@eTqa#!*6?8fsL{Wqw2mk;<5P&g;IF9k? z(Ib7$wdMfR(yp;At3v7q3GPu8VSRlaK@gx)sQ}|-SS%J3g;1tB!1k!w9^1kg%gp;y zN-)OI?RNDtN1kVl!S{XKy?Ym<(Flw&3_u=jJwmloCP+O@5f<2uZnIo>&p$ICg#lcU2)S5Qed(loPFS zv)M$a)4}QKDWWLSMwr_Gq?q}&1};I5Whv!ySucNt1XFo(3{{ITmdUwufVq~_zIk)n zr!o4q+tM^?Hk$yDsNP&c^}Uo5zVGXgF9G1=$B$r)IgS5Ubc0b8X+yY#xDJa34h{~mx3}kD$Qx?-^i-}e#6F}An2vAw-L!ACB&0Z7bN)+OzB8>gqI zkW%94=m_iU>$rFCUV<7U>imz@0rN_|UdNj^ZxYJ84AJZL5XUisAV9Cz!}|LAL=8eK zl&fW5N&^topFMkq;cy6ymEYRhnwU$SU=Re@+uPI1ld{v^7Gc?v;O6EghQlFBrIPmc za5%*N{yz5i_Y=pI+-3>qJn=4o>I4dhr7=LgUPlx~*xA{^&dv@>r4j((%a<aP61AhPhUGLLJkY{ISSY2IB zTr(Pt5XbREFF=T(SK?{Uv9z4v>gp;E4-fV6lP6D{^K7r$iq4|umYNg1bLY-n*K^Ki zzA?_E4)8n=oO4}v!r@`pOORaHfaC= literal 0 HcmV?d00001 diff --git a/resources/EngineResources/VoxelComputeShaders/meshGenerationShared.glsl b/resources/EngineResources/VoxelComputeShaders/meshGenerationShared.glsl index 0ed1040..844a691 100644 --- a/resources/EngineResources/VoxelComputeShaders/meshGenerationShared.glsl +++ b/resources/EngineResources/VoxelComputeShaders/meshGenerationShared.glsl @@ -32,11 +32,26 @@ layout(std430, binding = 3) buffer Counters { uint faceCount; } counters; +struct Voxel { + uint MaterialIndex; + uint BlockType; + uvec2[2] UpIndex; + uvec2[2] DownIndex; + uvec2[2] NorthIndex; + uvec2[2] SouthIndex; + uvec2[2] EastIndex; + uvec2[2] WestIndex; +}; + +layout(std430, set = 1, binding = 0) readonly buffer VoxelUniform { + Voxel materials[]; +} voxelReg; + layout(push_constant) uniform ChunkInfo { ivec3 chunkPos; int slot; uint faceOffset; - uint unused0; + uint voxelTypeCount; uint indirectCommandIndex; uint padding0; }; @@ -44,7 +59,10 @@ layout(push_constant) uniform ChunkInfo { uint flatten(ivec3 pos) { return uint((pos.x * CHUNK_AREA) + (pos.y * CHUNK_SIZE) + pos.z); } - +bool isSeeThrough(Voxel voxel, uint type) { + if (type == 0u || voxel.BlockType == 3u || type > voxelTypeCount) return true; + return voxelReg.materials[type - 1u].BlockType >= 1u; +} uint getVoxel(ivec3 pos) { if (pos.x < 0 || pos.x >= CHUNK_SIZE) return 0u; if (pos.y < 0 || pos.y >= CHUNK_SIZE) return 0u; @@ -58,7 +76,16 @@ uint hash21(uvec2 p) { p.y += p.x * 1664525u; return p.x ^ (p.x >> 16); } +uint pcg_hash(uint seed) { + uint state = seed * 747796405u + 289133645u; + uint word = ((state >> ((state >> 28u) + 4u)) ^ state) * 277803737u; + return (word >> 22u) ^ word; +} +uint randomRangeUint(uint seed, uint minVal, uint maxVal) { + uint range = maxVal - minVal + 1u; + return minVal + (pcg_hash(seed) % range); +} uint random_1_to_3(vec2 uv, uint customSeed) { uvec2 p = uvec2(floatBitsToUint(uv.x), floatBitsToUint(uv.y)); p.x ^= customSeed; @@ -66,6 +93,31 @@ uint random_1_to_3(vec2 uv, uint customSeed) { return (randInt % 3u) + 1u; } +uint packFace(uvec3 voxelPos, uint faceIndex, Voxel voxel) { + uint randomSeed = uint(voxelPos.x) * 73856093u ^ uint(voxelPos.z) * 19349663u; + uvec2 UpIndex = uvec2(randomRangeUint(randomSeed,voxel.UpIndex[0].x,voxel.UpIndex[1].x),randomRangeUint(randomSeed,voxel.UpIndex[0].y,voxel.UpIndex[1].y)); + uvec2 DownIndex = uvec2(randomRangeUint(randomSeed,voxel.DownIndex[0].x,voxel.DownIndex[1].x),randomRangeUint(randomSeed,voxel.DownIndex[0].y,voxel.DownIndex[1].y)); + uvec2 NorthIndex = uvec2(randomRangeUint(randomSeed,voxel.NorthIndex[0].x,voxel.NorthIndex[1].x),randomRangeUint(randomSeed,voxel.NorthIndex[0].y,voxel.NorthIndex[1].y)); + uvec2 SouthIndex = uvec2(randomRangeUint(randomSeed,voxel.SouthIndex[0].x,voxel.SouthIndex[1].x),randomRangeUint(randomSeed,voxel.SouthIndex[0].y,voxel.SouthIndex[1].y)); + uvec2 EastIndex = uvec2(randomRangeUint(randomSeed,voxel.EastIndex[0].x,voxel.EastIndex[1].x),randomRangeUint(randomSeed,voxel.EastIndex[0].y,voxel.EastIndex[1].y)); + uvec2 WestIndex = uvec2(randomRangeUint(randomSeed,voxel.WestIndex[0].x,voxel.WestIndex[1].x),randomRangeUint(randomSeed,voxel.WestIndex[0].y,voxel.WestIndex[1].y)); + + uvec2 textureIndices[8] = uvec2[8](UpIndex, DownIndex, NorthIndex, + SouthIndex, EastIndex, WestIndex, NorthIndex,SouthIndex); + uvec2 tex = textureIndices[faceIndex]; + uint textureIndexX = tex.x; + uint textureIndexY = tex.y; + uint materialId = voxel.MaterialIndex; + + return (voxelPos.x & 0xFu) | + ((voxelPos.y & 0xFu) << 4u) | + ((voxelPos.z & 0xFu) << 8u) | + ((faceIndex & 0x7u) << 12u) | + ((materialId & 0x7FFu) << 15u) | + ((textureIndexX & 0x7u) << 26u) | + ((textureIndexY & 0x7u) << 29u); +} + uint packFace(uvec3 voxelPos, uint faceIndex, uint materialId) { uint randomFaceValue = random_1_to_3(vec2(voxelPos.x, voxelPos.z),faceOffset); uint textureIndexX = 0u; @@ -107,23 +159,28 @@ uint packFace(uvec3 voxelPos, uint faceIndex, uint materialId) { textureIndexY = 0u; } - return (voxelPos.x & 0x1Fu) | - ((voxelPos.y & 0x1Fu) << 5u) | - ((voxelPos.z & 0x1Fu) << 10u) | - ((faceIndex & 0x7u) << 15u) | - ((materialId & 0xFFu) << 18u) | + return (voxelPos.x & 0xFu) | + ((voxelPos.y & 0xFu) << 4u) | + ((voxelPos.z & 0xFu) << 8u) | + ((faceIndex & 0x7u) << 12u) | + ((materialId & 0x7FFu) << 15u) | ((textureIndexX & 0x7u) << 26u) | ((textureIndexY & 0x7u) << 29u); } void emitFace(ivec3 voxelPos, uint faceIndex, uint voxelType) { + if (voxelType == 0u || voxelType > voxelTypeCount) { + return; + } + uint localFace = atomicAdd(counters.faceCount, 1u); if (localFace >= MAX_VISIBLE_FACES_PER_CHUNK) { return; } - faces[faceOffset + localFace] = packFace(uvec3(voxelPos), faceIndex, voxelType); + Voxel voxel = voxelReg.materials[voxelType - 1u]; + faces[faceOffset + localFace] = packFace(uvec3(voxelPos), faceIndex, voxel); atomicAdd(drawCmds[indirectCommandIndex].vertexCount, VERTICES_PER_FACE); } @@ -136,21 +193,20 @@ void main() { } uint current = getVoxel(pos); - - if (current == 0u) { + if (current == 0u || current > voxelTypeCount) { return; } - - if (current == 4u) { + Voxel voxel = voxelReg.materials[current - 1u]; + if (voxel.BlockType == 1u) { emitFace(pos, 6u, current); emitFace(pos, 7u, current); return; } - if (getVoxel(pos + ivec3( 0, 1, 0)) == 0u || getVoxel(pos + ivec3( 0, 1, 0)) == 4u) emitFace(pos, 0u, current); - if (getVoxel(pos + ivec3( 0, -1, 0)) == 0u || getVoxel(pos + ivec3( 0, -1, 0)) == 4u) emitFace(pos, 1u, current); - if (getVoxel(pos + ivec3( 1, 0, 0)) == 0u || getVoxel(pos + ivec3( 1, 0, 0)) == 4u) emitFace(pos, 2u, current); - if (getVoxel(pos + ivec3(-1, 0, 0)) == 0u || getVoxel(pos + ivec3( -1, 0, 0)) == 4u) emitFace(pos, 3u, current); - if (getVoxel(pos + ivec3( 0, 0, 1)) == 0u|| getVoxel(pos + ivec3( 0, 0, 1)) == 4u) emitFace(pos, 4u, current); - if (getVoxel(pos + ivec3( 0, 0, -1)) == 0u || getVoxel(pos + ivec3( 0, 0, -1)) == 4u) emitFace(pos, 5u, current); + if (isSeeThrough(voxel,getVoxel(pos + ivec3( 0, 1, 0)))) emitFace(pos, 0u, current); + if (isSeeThrough(voxel,getVoxel(pos + ivec3( 0, -1, 0)))) emitFace(pos, 1u, current); + if (isSeeThrough(voxel,getVoxel(pos + ivec3( 1, 0, 0)))) emitFace(pos, 2u, current); + if (isSeeThrough(voxel,getVoxel(pos + ivec3(-1, 0, 0)))) emitFace(pos, 3u, current); + if (isSeeThrough(voxel,getVoxel(pos + ivec3( 0, 0, 1)))) emitFace(pos, 4u, current); + if (isSeeThrough(voxel,getVoxel(pos + ivec3( 0, 0, -1)))) emitFace(pos, 5u, current); } \ No newline at end of file diff --git a/resources/EngineResources/VoxelComputeShaders/voxelGenerationShared.glsl b/resources/EngineResources/VoxelComputeShaders/voxelGenerationShared.glsl index 44ad8f3..e091158 100644 --- a/resources/EngineResources/VoxelComputeShaders/voxelGenerationShared.glsl +++ b/resources/EngineResources/VoxelComputeShaders/voxelGenerationShared.glsl @@ -8,6 +8,19 @@ const int CHUNK_AREA = CHUNK_SIZE * CHUNK_SIZE; layout(std430, binding = 0) buffer VoxelData { uint voxels[]; }; +struct Biome { + uint surfaceBlock; + uint dirtBlock; + uint stoneBlock; + uint grassFoliage; + uint[4] flowers; + uint[4] tallBlocks; + uint[4] otherFoliage; +}; + +layout(std430, set = 1, binding = 0) readonly buffer BiomeUniform { + Biome biomes[]; +} BiomeReg; layout(push_constant) uniform ChunkInfo { ivec3 chunkPos; @@ -15,15 +28,8 @@ layout(push_constant) uniform ChunkInfo { uint faceOffset; uint unused0; uint indirectCommandIndex; - uint padding0; + uint biomeCount; }; -vec3 random3(vec3 st) { - return fract(sin(vec3( - dot(st, vec3(127.1, 311.7, 74.7)), - dot(st, vec3(269.5, 183.3, 246.1)), - dot(st, vec3(113.5, 271.9, 124.6)) - )) * 43758.5453123); -} float random3to1(vec3 st) { return fract(sin(dot(st, vec3(127.1, 311.7, 74.7))) * 43758.5453123); @@ -88,6 +94,29 @@ float valueNoise(vec2 st) { (c - a) * u.y * (1.0 - u.x) + (d - b) * u.x * u.y; } + +uint pcg_hash(uint seed) { + uint state = seed * 747796405u + 289133645u; + uint word = ((state >> ((state >> 28u) + 4u)) ^ state) * 277803737u; + return (word >> 22u) ^ word; +} + +uint randomRangeUint(uint seed, uint minVal, uint maxVal) { + uint range = maxVal - minVal + 1u; + return minVal + (pcg_hash(seed) % range); +} + +uint GetBiome(vec3 worldPos, uint MaxBiomes) { + if (MaxBiomes == 0u) return 0u; + vec3 X = vec3(worldPos); + X = mat3( + 0.788675134594813, -0.211324865405187, -0.577350269189626, + -0.211324865405187, 0.788675134594813, -0.577350269189626, + 0.577350269189626, 0.577350269189626, 0.577350269189626) * X; + float n = clamp(cubicNoise(X), 0.0, 0.9999); + uint Biome = uint(floor(n * float(MaxBiomes))); + return min(Biome, MaxBiomes - 1u); +} bool isCave(vec3 worldPos) { vec3 X = vec3(worldPos); X = mat3( @@ -101,33 +130,41 @@ bool isCave(vec3 worldPos) { void main() { ivec3 localPos = ivec3(gl_GlobalInvocationID.xyz); ivec3 worldPos = chunkPos * CHUNK_SIZE + localPos; - + + uint biome = GetBiome(vec3(worldPos.z, worldPos.y, worldPos.x) * 0.05, biomeCount); + Biome currentBiome = BiomeReg.biomes[biome]; + float YZone = floor(worldPos.y/150.0)*150.0; - float SurfaceHeight = valueNoise(vec2(worldPos.x + YZone * 2, worldPos.z + YZone * 2) * 0.005) * 100 + + float SurfaceHeight = valueNoise(vec2(worldPos.x + YZone * 2, worldPos.z + YZone * 2) * 0.005) * 100 + + valueNoise(vec2(worldPos.x + YZone * 2, worldPos.z + YZone * 2) * 0.01) * 10 + valueNoise(vec2(worldPos.x + YZone * 2, worldPos.z + YZone * 2) * 0.1) * 5 + valueNoise(vec2(worldPos.x + YZone * 2, worldPos.z + YZone * 2)) * 0.5 + YZone; + uint RandomBlockVal = randomRangeUint(uint(worldPos.x) * 73856093u ^ uint(worldPos.z) * 19349663u,0u ,3u); float IslandUnderneathHeight = valueNoise(vec2(worldPos.x + YZone * 2, worldPos.z + YZone * 2) * 0.005) * 100 + + valueNoise(vec2(worldPos.x + YZone * 2, worldPos.z + YZone * 2) * 0.1) * 20 + valueNoise(vec2(worldPos.x + YZone * 2, worldPos.z + YZone * 2) * 0.1) * 5 + valueNoise(vec2(worldPos.x + YZone * 2, worldPos.z + YZone * 2)) * 0.5 - 15 + YZone; - float grassNoise = valueNoise(vec2(worldPos.z + YZone * 2, worldPos.x + YZone * 2)); + float grassNoise = valueNoise(vec2(worldPos.z * 0.5 - YZone * 2, worldPos.x * 0.5 - YZone * 2)); uint voxelType = 0u; if (float(worldPos.y) <= SurfaceHeight && float(worldPos.y) >= IslandUnderneathHeight) { float depthBelowSurface = SurfaceHeight - float(worldPos.y); if (depthBelowSurface < 0.5) { - if(grassNoise < 0.65) voxelType = 4u; // Grass foliage + if(grassNoise < 0.65) voxelType = currentBiome.grassFoliage; // Grass foliage + else if (grassNoise < 0.75) voxelType = currentBiome.flowers[RandomBlockVal]; + else if (grassNoise < 0.85) voxelType = currentBiome.otherFoliage[RandomBlockVal]; else voxelType = 0u; }else if (depthBelowSurface < 2.5) { - voxelType = 1u; // Grass + voxelType = currentBiome.surfaceBlock; // Grass } else if (depthBelowSurface < 6.0) { - voxelType = 2u; // Dirt(also stone rn) + voxelType = currentBiome.dirtBlock; // Dirt(also stone rn) } else { - voxelType = 3u; // Stone + voxelType = currentBiome.stoneBlock; // Stone } } else{ @@ -145,14 +182,16 @@ void main() { float depthBelowSurface = height2 - float(worldPos.y); if (depthBelowSurface < 0.5) { - if (grassNoise < 0.65) voxelType = 4u; // Grass foliage + if (grassNoise < 0.65) voxelType = currentBiome.grassFoliage; // Grass foliage + else if (grassNoise < 0.75) voxelType = currentBiome.flowers[RandomBlockVal]; + else if (grassNoise < 0.85) voxelType = currentBiome.otherFoliage[RandomBlockVal]; else voxelType = 0u; } else if (depthBelowSurface < 1.5) { - voxelType = 1u; // Grass + voxelType = currentBiome.surfaceBlock; // Grass } else if (depthBelowSurface < 6.0) { - voxelType = 2u; // Dirt(also stone rn) + voxelType = currentBiome.dirtBlock; // Dirt(also stone rn) } else { - voxelType = 3u; // Stone + voxelType = currentBiome.stoneBlock; // Stone } } } diff --git a/resources/EngineResources/shaders/packed_scene_fragment.glsl b/resources/EngineResources/shaders/packed_scene_fragment.glsl new file mode 100644 index 0000000..d31628a --- /dev/null +++ b/resources/EngineResources/shaders/packed_scene_fragment.glsl @@ -0,0 +1,88 @@ +#version 450 +#extension GL_EXT_nonuniform_qualifier : require + +const int MAX_TEXTURES = 128; + +layout(location = 0) in vec4 inPos; +layout(location = 1) in vec3 inNormal; +layout(location = 2) in vec3 inTangent; +layout(location = 3) in vec3 inBitangent; +layout(location = 4) in vec2 inTextCoords; +layout(location = 5) in mat4 viewMatrix; +layout(location = 9) in flat uint textureIndex; + +layout(location = 0) out vec4 outAlbedo; +layout(location = 1) out vec4 outViewPos; + +struct Material { + vec4 diffuseColor; //16 + uint hasTexture; //20 + uint textureIdx; //24 + uint hasNormalMap; //28 + uint normalMapIdx; //32 + uint hasRoughMap; //36 + uint roughMapIdx; //40 + float roughnessFactor; //44 + float metallicFactor; //48 + vec4 emissiveColour; //64 + uint hasEmissiveMap; //68 + uint emissiveMapIdx; //72 + uint hasTranslucencyMap; //76 + uint translucencyMapIdx; //80 + float translucencyFactor; //84 + uint hasOpacityMap; //88 + uint OpacityMapIdx; //92 + float OpacityFactor; //96 + float reflectiveness; //100 + float refractiveness; //104 + float Padding1; //108 + float Padding2; //112 +}; + +layout(set = 2, binding = 0) readonly buffer MaterialUniform{ + Material materials[]; +} matUniform; + +layout(set = 3, binding = 0) uniform sampler2D textSampler[MAX_TEXTURES]; + + +layout(push_constant) uniform pc{ + layout(offset = 64) uint materialIdx; +} push_constants; + +void main() +{ + vec4 viewPos = vec4(viewMatrix * inPos); + outViewPos = viewPos; + + Material material = matUniform.materials[textureIndex]; + + uint albedoTextureIndex = material.textureIdx; + if (albedoTextureIndex >= MAX_TEXTURES){ + outAlbedo = vec4(0.0,0.0,1.0,1.0); + return; + } + + if(material.hasTexture == 1){ + vec4 texColor = texture(textSampler[nonuniformEXT(albedoTextureIndex)], inTextCoords); + outAlbedo = texColor; + } else{ + outAlbedo = material.diffuseColor; + } + + vec4 Opacity = vec4(outAlbedo.a, outAlbedo.a, outAlbedo.a, 1.0); + + if (material.OpacityFactor > 0.0 && material.OpacityFactor < 1.0) { + Opacity = vec4(material.OpacityFactor, material.OpacityFactor, material.OpacityFactor, 1.0); + } + + if (material.hasOpacityMap > 0 && material.OpacityMapIdx < MAX_TEXTURES) { + Opacity = texture(textSampler[nonuniformEXT(material.OpacityMapIdx)], inTextCoords); + } + + float opacityf = Opacity.x + Opacity.y + Opacity.z; + opacityf = opacityf / 3; + if(opacityf < 0.4){ discard; } + + outAlbedo = vec4(outAlbedo.rgb, opacityf); +} \ No newline at end of file diff --git a/resources/EngineResources/shaders/packed_scene_fragment_deferred.glsl b/resources/EngineResources/shaders/packed_scene_fragment_deferred.glsl new file mode 100644 index 0000000..8f5d5bf --- /dev/null +++ b/resources/EngineResources/shaders/packed_scene_fragment_deferred.glsl @@ -0,0 +1,149 @@ +#version 450 +#extension GL_EXT_nonuniform_qualifier : require + +const int MAX_TEXTURES = 128; + + +layout(location = 0) in vec4 inPos; +layout(location = 1) in vec3 inNormal; +layout(location = 2) in vec3 inTangent; +layout(location = 3) in vec3 inBitangent; +layout(location = 4) in vec2 inTextCoords; +layout(location = 5) in mat4 viewMatrix; +layout(location = 9) in flat uint MaterialID; + +layout(location = 1) out vec4 outAlbedo ; +layout(location = 0) out vec4 outPos; +layout(location = 2) out vec4 outNormal; +layout(location = 3) out vec4 outPBR; +layout(location = 4) out vec4 outEmissive; +layout(location = 5) out vec4 outTranslucency; +layout(location = 6) out vec4 outOpacity; +layout(location = 7) out vec4 outViewPos; + +struct Material { + vec4 diffuseColor; //16 + uint hasTexture; //20 + uint textureIdx; //24 + uint hasNormalMap; //28 + uint normalMapIdx; //32 + uint hasRoughMap; //36 + uint roughMapIdx; //40 + float roughnessFactor; //44 + float metallicFactor; //48 + vec4 emissiveColour; //64 + uint hasEmissiveMap; //68 + uint emissiveMapIdx; //72 + uint hasTranslucencyMap; //76 + uint translucencyMapIdx; //80 + float translucencyFactor; //84 + uint hasOpacityMap; //88 + uint OpacityMapIdx; //92 + float OpacityFactor; //96 + float reflectiveness; //100 + float refractiveness; //104 + float Padding1; //108 + float Padding2; //112 +}; +layout(set = 2, binding = 0) readonly buffer MaterialUniform { + Material materials[]; +} matUniform; +layout(set = 3, binding = 0) uniform sampler2D textSampler[MAX_TEXTURES]; + +vec3 calcNormal(Material material, vec3 normal, vec2 textCoords, mat3 TBN) +{ + vec3 newNormal = normal; + if (material.hasNormalMap > 0 && material.normalMapIdx < MAX_TEXTURES) + { + newNormal = texture(textSampler[nonuniformEXT(material.normalMapIdx)], textCoords).rgb; + newNormal = normalize(newNormal * 2.0 - 1.0); + newNormal = normalize(TBN * newNormal); + } + return newNormal; +} + +layout(push_constant) uniform pc { + layout(offset = 64) uint materialIdx; +} push_constants; + +void main() +{ + outPos = inPos; + + vec4 viewPos = vec4(viewMatrix * vec4(inPos.xyz, 1.0)); + outViewPos = viewPos; + + Material material = matUniform.materials[MaterialID]; + + uint albedoTextureIndex = material.textureIdx; + if (albedoTextureIndex >= MAX_TEXTURES) { + outAlbedo = vec4(0.0,0.0,1.0,1.0); + outOpacity = vec4(0.0,0.0,1.0,1.0); + outNormal = vec4(0.0,0.0,1.0,1.0); + outEmissive = vec4(0.0,0.0,1.0,1.0); + outTranslucency = vec4(0.0,0.0,1.0,1.0); + outPBR = vec4(0.0,0.0,1.0,1.0); + return; + } + + if (material.hasTexture == 1) { + outAlbedo = texture(textSampler[nonuniformEXT(albedoTextureIndex)], inTextCoords); + } else { + outAlbedo = material.diffuseColor; + } + + vec4 Opacity = vec4(outAlbedo.a, outAlbedo.a, outAlbedo.a, 1.0); + + if (material.OpacityFactor > 0.0 && material.OpacityFactor < 1.0) { + Opacity = vec4(material.OpacityFactor, material.OpacityFactor, material.OpacityFactor, 1.0); + } + + if (material.hasOpacityMap > 0 && material.OpacityMapIdx < MAX_TEXTURES) { + outOpacity = texture(textSampler[nonuniformEXT(material.OpacityMapIdx)], inTextCoords); + } else { + outOpacity = Opacity; + } + + Opacity = outOpacity; + + float opacityf = Opacity.x + Opacity.y + Opacity.z; + opacityf = opacityf / 3; + + outAlbedo = vec4(outAlbedo.rgb, opacityf); + + if(outAlbedo.a < 0.5) discard; + + mat3 TBN = mat3(inTangent, inBitangent, inNormal); + vec3 newNormal = calcNormal(material, inNormal, inTextCoords, TBN); + + float ao = 0.5f; + float roughnessFactor = 0.0f; + float metallicFactor = 0.0f; + + if (material.hasRoughMap > 0 && material.roughMapIdx < MAX_TEXTURES) { + vec4 metRoughValue = texture(textSampler[nonuniformEXT(material.roughMapIdx)], inTextCoords); + roughnessFactor = metRoughValue.g; + metallicFactor = metRoughValue.b; + } else { + roughnessFactor = material.roughnessFactor; + metallicFactor = material.metallicFactor; + } + + vec4 emissive = material.emissiveColour; + if (material.hasEmissiveMap > 0 && material.emissiveMapIdx < MAX_TEXTURES) { + emissive = texture(textSampler[nonuniformEXT(material.emissiveMapIdx)], inTextCoords); + } + outEmissive = emissive; + + vec4 Translucency = vec4(material.translucencyFactor, material.translucencyFactor, material.translucencyFactor, 1); + if(material.hasTranslucencyMap > 0 && material.translucencyMapIdx < MAX_TEXTURES){ + Translucency = texture(textSampler[nonuniformEXT(material.translucencyMapIdx)], inTextCoords); + } + outTranslucency = Translucency; + + float Refractiveness = material.refractiveness; + float Reflectiveness = material.reflectiveness; + + outNormal = vec4(newNormal, Refractiveness); + outPBR = vec4(ao, roughnessFactor, metallicFactor, Reflectiveness); +} \ No newline at end of file diff --git a/resources/EngineResources/shaders/packed_scene_vertex.glsl b/resources/EngineResources/shaders/packed_scene_vertex.glsl index 6e125f4..be818ae 100644 --- a/resources/EngineResources/shaders/packed_scene_vertex.glsl +++ b/resources/EngineResources/shaders/packed_scene_vertex.glsl @@ -6,6 +6,7 @@ layout(location = 2) out vec3 outTangent; layout(location = 3) out vec3 outBitangent; layout(location = 4) out vec2 outTextCoords; layout(location = 5) out mat4 viewMatrix; +layout(location = 9) out flat uint outMaterialID; layout(set = 0, binding = 0) uniform ProjUniform { mat4 matrix; } projUniform; layout(set = 1, binding = 0) uniform ViewUniform { mat4 matrix; } viewUniform; @@ -93,17 +94,13 @@ void main() { uint triangleVertex = (uint(gl_VertexIndex))% 6u; uint cornerIndex = TRI_TO_CORNER[triangleVertex]; - //uint faceRecordIndex = uint(gl_VertexIndex) / 6u; - //uint triangleVertex = uint(gl_VertexIndex) % 6u; - //uint cornerIndex = TRI_TO_CORNER[triangleVertex]; - uint packedFace = faces[faceRecordIndex]; - uint voxelX = packedFace & 0x1Fu; - uint voxelY = (packedFace >> 5u) & 0x1Fu; - uint voxelZ = (packedFace >> 10u) & 0x1Fu; - uint faceId = (packedFace >> 15u) & 0x7u; - uint matId = (packedFace >> 18u) & 0xFFu; + uint voxelX = packedFace & 0xFu; + uint voxelY = (packedFace >> 4u) & 0xFu; + uint voxelZ = (packedFace >> 8u) & 0xFu; + uint faceId = (packedFace >> 12u) & 0x7u; + uint matId = (packedFace >> 15u) & 0x7FFu; uint texIdxX = (packedFace >> 26u) & 0x7u; uint texIdxY = (packedFace >> 29u) & 0x7u; @@ -111,7 +108,6 @@ void main() { vec2 scalar = vec2(1.0/4.0,1.0/4.0); faceId = min(faceId, 7u); - matId = min(matId, 4u); vec3 localPos = vec3(voxelX, voxelY, voxelZ) + FACE_CORNERS[faceId][cornerIndex]; vec3 worldPos = localPos + push_constants.ModelOffset.xyz * 16.0; @@ -119,10 +115,14 @@ void main() { vec4 worldPosVec4 = vec4(worldPos, 1.0); gl_Position = projUniform.matrix * viewUniform.matrix * worldPosVec4; - outPos = worldPosVec4; outNormal = NORMALS[faceId]; outTangent = TANGENTS[faceId]; outBitangent = BITANGENTS[faceId]; - outTextCoords = CORNER_UVS_GRASS_BLOCK[faceId][cornerIndex] * scalar + texID; + vec2 atlasSize = vec2(64, 64); + vec2 texel = 0.5 / atlasSize; + vec2 tileMin = vec2(texIdxX, texIdxY) * scalar + texel; + vec2 tileMax = vec2(texIdxX + 1u, texIdxY + 1u) * scalar - texel; + outTextCoords = mix(tileMin, tileMax, CORNER_UVS_GRASS_BLOCK[faceId][cornerIndex]); + outMaterialID = matId; } \ No newline at end of file diff --git a/resources/EngineResources/shaders/shadow_vertex_packed.glsl b/resources/EngineResources/shaders/shadow_vertex_packed.glsl index 8833df7..7fc691a 100644 --- a/resources/EngineResources/shaders/shadow_vertex_packed.glsl +++ b/resources/EngineResources/shaders/shadow_vertex_packed.glsl @@ -17,6 +17,69 @@ layout(location = 1) out flat uint outMaterialIdx; const uint TRI_TO_CORNER[6] = uint[6](0u, 1u, 2u, 0u, 2u, 3u); +const vec3 NORMALS[8] = vec3[8]( + vec3( 0.0, 1.0, 0.0), // Face 0 (+Y) + vec3( 0.0, -1.0, 0.0), // Face 1 (-Y) + vec3( 1.0, 0.0, 0.0), // Face 2 (+X) + vec3(-1.0, 0.0, 0.0), // Face 3 (-X) + vec3( 0.0, 0.0, 1.0), // Face 4 (+Z) + vec3( 0.0, 0.0, -1.0), // Face 5 (-Z) + vec3(-0.7071, 0.0, 0.7071), // Face 6 + vec3( 0.7071, 0.0, 0.7071) // Face 7 +); + +const vec3 TANGENTS[8] = vec3[8]( + vec3( 1.0, 0.0, 0.0), // Face 0 + vec3( 1.0, 0.0, 0.0), // Face 1 + vec3( 0.0, 0.0, -1.0), // Face 2 + vec3( 0.0, 0.0, 1.0), // Face 3 + vec3( 1.0, 0.0, 0.0), // Face 4 + vec3(-1.0, 0.0, 0.0), // Face 5 + vec3( 0.7071, 0.0, 0.7071), // Face 6 + vec3( 0.7071, 0.0,-0.7071) // Face 7 +); + +const vec3 BITANGENTS[8] = vec3[8]( + vec3( 0.0, 0.0, 1.0), // Face 0 + vec3( 0.0, 0.0, -1.0), // Face 1 + vec3( 0.0, 1.0, 0.0), // Face 2 + vec3( 0.0, 1.0, 0.0), // Face 3 + vec3( 0.0, 1.0, 0.0), // Face 4 + vec3( 0.0, 1.0, 0.0), // Face 5 + vec3( 0.0, 1.0, 0.0), // Face 6 + vec3( 0.0, 1.0, 0.0) // Face 7 +); + +const vec2 CORNER_UVS[5][4] = vec2[5][4]( + vec2[4](vec2(0.5, 0.0), vec2(0.5, 0.5), vec2(1.0, 0.5), vec2(1.0, 0.0)), + vec2[4](vec2(0.0, 0.5), vec2(0.0, 1.0), vec2(0.5, 1.0), vec2(0.5, 0.5)), + vec2[4](vec2(0.5, 0.0), vec2(0.5, 0.5), vec2(1.0, 0.5), vec2(1.0, 0.0)), + vec2[4](vec2(0.5, 0.0), vec2(0.5, 0.5), vec2(1.0, 0.5), vec2(1.0, 0.0)), + vec2[4](vec2(1.0, 1.0), vec2(1.0, 0.5), vec2(0.5, 0.5), vec2(0.5, 1.0)) +); +const vec2 CORNER_UVS_GRASS_BLOCK[8][4] = vec2[8][4]( + vec2[4](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0)), + vec2[4](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0)), + vec2[4](vec2(1.0, 1.0), vec2(1.0, 0.0),vec2(0.0, 0.0), vec2(0.0, 1.0)), + vec2[4]( vec2(0.0, 1.0),vec2(1.0, 1.0), vec2(1.0, 0.0),vec2(0.0, 0.0)), + vec2[4]( vec2(0.0, 1.0),vec2(1.0, 1.0), vec2(1.0, 0.0),vec2(0.0, 0.0)), + vec2[4](vec2(1.0, 1.0), vec2(1.0, 0.0),vec2(0.0, 0.0), vec2(0.0, 1.0)), + vec2[4](vec2(1.0, 1.0), vec2(1.0, 0.0), vec2(0.0, 0.0), vec2(0.0, 1.0)), + vec2[4](vec2(1.0, 1.0), vec2(1.0, 0.0), vec2(0.0, 0.0), vec2(0.0, 1.0)) + +); + +const vec3 FACE_CORNERS[8][4] = vec3[8][4]( + vec3[4](vec3(0.0, 1.0, 0.0), vec3(0.0, 1.0, 1.0), vec3(1.0, 1.0, 1.0), vec3(1.0, 1.0, 0.0)), // Face 0 (+Y) + vec3[4](vec3(0.0, 0.0, 0.0), vec3(1.0, 0.0, 0.0), vec3(1.0, 0.0, 1.0), vec3(0.0, 0.0, 1.0)), // Face 1 (-Y) + vec3[4](vec3(1.0, 0.0, 0.0), vec3(1.0, 1.0, 0.0), vec3(1.0, 1.0, 1.0), vec3(1.0, 0.0, 1.0)), // Face 2 (+X) + vec3[4](vec3(0.0, 0.0, 0.0), vec3(0.0, 0.0, 1.0), vec3(0.0, 1.0, 1.0), vec3(0.0, 1.0, 0.0)), // Face 3 (-X) + vec3[4](vec3(0.0, 0.0, 1.0), vec3(1.0, 0.0, 1.0), vec3(1.0, 1.0, 1.0), vec3(0.0, 1.0, 1.0)), // Face 4 (+Z) + vec3[4](vec3(0.0, 0.0, 0.0), vec3(0.0, 1.0, 0.0), vec3(1.0, 1.0, 0.0), vec3(1.0, 0.0, 0.0)), // Face 5 (-Z) + vec3[4](vec3(0.0, 0.0, 0.0), vec3(0.0, 1.0, 0.0), vec3(1.0, 1.0, 1.0), vec3(1.0, 0.0, 1.0)), // Face 6 (cross model pane 1) + vec3[4](vec3(0.0, 0.0, 1.0), vec3(0.0, 1.0, 1.0), vec3(1.0, 1.0, 0.0), vec3(1.0, 0.0, 0.0)) // Face 7 (cross model pane 2) +); + vec3 buildFaceCornerPosition(uvec3 voxelPos, uint faceId, uint cornerIndex) { vec3 p = vec3(voxelPos); @@ -63,21 +126,40 @@ vec3 buildFaceCornerPosition(uvec3 voxelPos, uint faceId, uint cornerIndex) { void main() { uint faceRecordIndex = uint(gl_VertexIndex) / 6u; - uint triangleVertex = uint(gl_VertexIndex) % 6u; + uint triangleVertex = (uint(gl_VertexIndex))% 6u; uint cornerIndex = TRI_TO_CORNER[triangleVertex]; + //uint faceRecordIndex = uint(gl_VertexIndex) / 6u; + //uint triangleVertex = uint(gl_VertexIndex) % 6u; + //uint cornerIndex = TRI_TO_CORNER[triangleVertex]; + uint packedFace = faces[faceRecordIndex]; - uint voxelX = packedFace & 0x1Fu; - uint voxelY = (packedFace >> 5u) & 0x1Fu; - uint voxelZ = (packedFace >> 10u) & 0x1Fu; - uint faceId = (packedFace >> 15u) & 0x7u; - uint matId = (packedFace >> 18u) & 0xFFu; + uint voxelX = packedFace & 0xFu; + uint voxelY = (packedFace >> 4u) & 0xFu; + uint voxelZ = (packedFace >> 8u) & 0xFu; + uint faceId = (packedFace >> 12u) & 0x7u; + uint matId = (packedFace >> 15u) & 0x7FFu; + uint texIdxX = (packedFace >> 26u) & 0x7u; + uint texIdxY = (packedFace >> 29u) & 0x7u; - vec3 localPos = buildFaceCornerPosition(uvec3(voxelX, voxelY, voxelZ), faceId, cornerIndex); + // (voxelPos.x & 0xFu) | + // ((voxelPos.y & 0xFu) << 4u) | + // ((voxelPos.z & 0xFu) << 8u) | + // ((faceIndex & 0x7u) << 12u) | + // ((materialId & 0x7FFu) << 15u) | + // ((textureIndexX & 0x7u) << 26u) | + // ((textureIndexY & 0x7u) << 29u); + + vec2 texID = vec2((texIdxX)/4.0,(texIdxY)/4.0); + vec2 scalar = vec2(1.0/4.0,1.0/4.0); + + faceId = min(faceId, 7u); + + vec3 localPos = vec3(voxelX, voxelY, voxelZ) + FACE_CORNERS[faceId][cornerIndex]; vec3 worldPos = localPos + push_constants.ModelOffset.xyz * 16.0; - outTextCoord = vec2(0.0); + outTextCoord = CORNER_UVS_GRASS_BLOCK[faceId][cornerIndex] * scalar + texID; outMaterialIdx = matId; gl_Position = vec4(worldPos, 1.0); diff --git a/resources/EngineResources/shaders/water_frag.glsl b/resources/EngineResources/shaders/water_frag.glsl new file mode 100644 index 0000000..745b053 --- /dev/null +++ b/resources/EngineResources/shaders/water_frag.glsl @@ -0,0 +1,51 @@ +#version 460 core + +in vec3 FragPos; +in vec2 TexCoords; +in vec3 Normal; + +out vec4 FragColor; + +uniform vec3 cameraPos; +uniform vec3 lightPos; + +// Material constants +const vec3 waterShallowColor = vec3(0.0, 0.6, 0.7); +const vec3 waterDeepColor = vec3(0.05, 0.15, 0.3); +const vec3 sunColor = vec3(1.0, 0.95, 0.8); + +void main() { + // Normalize vectors + vec3 n = normalize(Normal); + vec3 viewDir = normalize(cameraPos - FragPos); + vec3 lightDir = normalize(lightPos - FragPos); + + // 1. Ambient Lighting + vec3 ambient = 0.3 * waterShallowColor; + + // 2. Diffuse Shading + float diff = max(dot(n, lightDir), 0.0); + vec3 diffuse = diff * sunColor * 0.4; + + // 3. Specular Highlights (Blinn-Phong) + vec3 halfwayDir = normalize(lightDir + viewDir); + float spec = pow(max(dot(n, halfwayDir), 0.0), 64.0); // High shininess for water glaze + vec3 specular = spec * sunColor * 0.8; + + // 4. Fresnel Approximation (Schlick's approximation) + // Water has a base reflectivity of roughly 0.02 at a perpendicular view angle + float F0 = 0.02; + float fresnel = F0 + (1.0 - F0) * pow(1.0 - max(dot(n, viewDir), 0.0), 5.0); + + // Mix deep and shallow water colors based on the normal angle + vec3 baseWaterColor = mix(waterShallowColor, waterDeepColor, max(dot(n, vec3(0.0, 1.0, 0.0)), 0.0)); + + // Combine lighting results + vec3 lightingResult = ambient + diffuse + specular; + + // Blend final look with Fresnel reflection dominance + vec3 finalColor = mix(baseWaterColor + specular, lightingResult + vec3(fresnel * 0.5), fresnel); + + // Output final color with subtle translucency opacity + FragColor = vec4(finalColor, 0.85); +} diff --git a/resources/EngineResources/shaders/water_vert.glsl b/resources/EngineResources/shaders/water_vert.glsl new file mode 100644 index 0000000..ac3c0a1 --- /dev/null +++ b/resources/EngineResources/shaders/water_vert.glsl @@ -0,0 +1,46 @@ +#version 450 + +layout (location = 0) in vec3 aPos; +layout (location = 1) in vec2 aTexCoords; + +out vec3 FragPos; +out vec2 TexCoords; +out vec3 Normal; + +uniform mat4 model; +uniform mat4 view; +uniform mat4 projection; +uniform float uTime; + +// Wave configuration constants +const float AMPLITUDE = 0.15; +const float FREQUENCY = 1.5; +const float SPEED = 2.0; + +// Simple wave function that modifies elevation based on position and time +float calculateWave(vec3 pos, float time, vec2 direction) { + return AMPLITUDE * sin(dot(pos.xz, direction) * FREQUENCY + time * SPEED); +} + +// Derivative of the wave function to calculate accurate dynamic surface normals +vec3 calculateWaveNormal(vec3 pos, float time) { + float dx = AMPLITUDE * FREQUENCY * cos(pos.x * FREQUENCY + time * SPEED); + float dz = AMPLITUDE * FREQUENCY * cos(pos.z * FREQUENCY + time * SPEED); + return normalize(vec3(-dx, 1.0, -dz)); +} + +void main() { + vec3 displacedPos = aPos; + + // Combine two wave directions for a less predictable, more organic look + displacedPos.y += calculateWave(aPos, uTime, vec2(1.0, 0.0)); + displacedPos.y += calculateWave(aPos, uTime * 1.2, vec2(0.5, 0.8)); + + FragPos = vec3(model * vec4(displacedPos, 1.0)); + TexCoords = aTexCoords; + + // Pass transformed normals and position to the fragment shader + Normal = mat3(transpose(inverse(model))) * calculateWaveNormal(displacedPos, uTime); + + gl_Position = projection * view * model * vec4(displacedPos, 1.0); +} diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Display/VulkanRenderer.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Display/VulkanRenderer.java index fd49cf3..a1b633a 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Display/VulkanRenderer.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Display/VulkanRenderer.java @@ -5,6 +5,8 @@ import net.halbear.Terrain4J.EngineCore.Logic.EngineInstance; import net.halbear.Terrain4J.EngineCore.Logic.InitData; import net.halbear.Terrain4J.EngineCore.Logic.Rendering.SkyBox; import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext; +import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Computing.VoxelTerrainGeneration.Biome; +import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Computing.VoxelTerrainGeneration.Voxel; import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Computing.VoxelTerrainGeneration.VoxelChunkGenerator; import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Computing.VoxelTerrainGeneration.VoxelWorldManager; import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.RenderPasses.GUI.GuiRenderer; @@ -30,6 +32,7 @@ import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Structure.SwapChain. import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Structure.SwapChain.SwapChainRender; import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Util.VulkanUtils; import net.halbear.Terrain4J.EngineCore.Threads.RenderThread; +import org.joml.Vector2i; import org.joml.Vector3f; import org.joml.Vector3i; import org.lwjgl.system.MemoryStack; @@ -188,6 +191,190 @@ public class VulkanRenderer implements Renderer { GuiRender.LoadTextures(RendererContext,initData.GuiTextures(),textureCache); //VoxelWorldManager.Init(RendererContext); // VoxelWorldManager.GenerateChunks(new Vector3i(0,0,0), new Vector3i(16,0,16)); + Vector2i positionArr[][] = new Vector2i[4][4]; + for(int x = 0; x < 4; x++){ + for(int y = 0; y < 4; y++){ + positionArr[x][y] = new Vector2i(x,y); + } + } + int Index = materialsCache.GetPosition("VoxelTerrain"); + int Index2 = materialsCache.GetPosition("Blueleaf"); + int Index3 = materialsCache.GetPosition("Blueleaf2"); + Voxel grassVoxel = new Voxel(Index, 0, + new Vector2i[]{positionArr[0][1], positionArr[0][3]}, + new Vector2i[]{positionArr[1][0], positionArr[1][0]}, + new Vector2i[]{positionArr[0][0], positionArr[0][0]}, + new Vector2i[]{positionArr[0][0], positionArr[0][0]}, + new Vector2i[]{positionArr[0][0], positionArr[0][0]}, + new Vector2i[]{positionArr[0][0], positionArr[0][0]}); + + Voxel stoneVoxel = new Voxel(Index, 0, + new Vector2i[]{positionArr[1][0], positionArr[1][0]}, + new Vector2i[]{positionArr[1][0], positionArr[1][0]}, + new Vector2i[]{positionArr[1][0], positionArr[1][0]}, + new Vector2i[]{positionArr[1][0], positionArr[1][0]}, + new Vector2i[]{positionArr[1][0], positionArr[1][0]}, + new Vector2i[]{positionArr[1][0], positionArr[1][0]}); + + Voxel grassSideVoxel = new Voxel(Index, 1, + new Vector2i[]{positionArr[1][1], positionArr[1][3]}, + new Vector2i[]{positionArr[1][1], positionArr[1][3]}, + new Vector2i[]{positionArr[1][1], positionArr[1][3]}, + new Vector2i[]{positionArr[1][1], positionArr[1][3]}, + new Vector2i[]{positionArr[1][1], positionArr[1][3]}, + new Vector2i[]{positionArr[1][1], positionArr[1][3]}); + Voxel Mushroom = new Voxel(Index, 1, + new Vector2i[]{positionArr[2][3], positionArr[2][3]}, + new Vector2i[]{positionArr[2][3], positionArr[2][3]}, + new Vector2i[]{positionArr[2][3], positionArr[2][3]}, + new Vector2i[]{positionArr[2][3], positionArr[2][3]}, + new Vector2i[]{positionArr[2][3], positionArr[2][3]}, + new Vector2i[]{positionArr[2][3], positionArr[2][3]}); + + Voxel Log = new Voxel(Index, 0, + new Vector2i[]{positionArr[2][1], positionArr[2][1]}, + new Vector2i[]{positionArr[2][1], positionArr[2][1]}, + new Vector2i[]{positionArr[2][2], positionArr[2][2]}, + new Vector2i[]{positionArr[2][2], positionArr[2][2]}, + new Vector2i[]{positionArr[2][2], positionArr[2][2]}, + new Vector2i[]{positionArr[2][2], positionArr[2][2]}); + + Voxel Leaves = new Voxel(Index, 2, + new Vector2i[]{positionArr[2][0], positionArr[2][0]}, + new Vector2i[]{positionArr[2][0], positionArr[2][0]}, + new Vector2i[]{positionArr[2][0], positionArr[2][0]}, + new Vector2i[]{positionArr[2][0], positionArr[2][0]}, + new Vector2i[]{positionArr[2][0], positionArr[2][0]}, + new Vector2i[]{positionArr[2][0], positionArr[2][0]}); + + Voxel bluegrassVoxel = new Voxel(Index2, 0, + new Vector2i[]{positionArr[0][1], positionArr[1][3]}, + new Vector2i[]{positionArr[1][0], positionArr[1][0]}, + new Vector2i[]{positionArr[0][0], positionArr[0][0]}, + new Vector2i[]{positionArr[0][0], positionArr[0][0]}, + new Vector2i[]{positionArr[0][0], positionArr[0][0]}, + new Vector2i[]{positionArr[0][0], positionArr[0][0]}); + + Voxel blueDirtVoxel = new Voxel(Index2, 0, + new Vector2i[]{positionArr[1][0], positionArr[1][0]}, + new Vector2i[]{positionArr[1][0], positionArr[1][0]}, + new Vector2i[]{positionArr[1][0], positionArr[1][0]}, + new Vector2i[]{positionArr[1][0], positionArr[1][0]}, + new Vector2i[]{positionArr[1][0], positionArr[1][0]}, + new Vector2i[]{positionArr[1][0], positionArr[1][0]}); + + Voxel bluegrassSideVoxel = new Voxel(Index3, 1, + new Vector2i[]{positionArr[0][0], positionArr[1][2]}, + new Vector2i[]{positionArr[0][0], positionArr[1][2]}, + new Vector2i[]{positionArr[0][0], positionArr[1][2]}, + new Vector2i[]{positionArr[0][0], positionArr[1][2]}, + new Vector2i[]{positionArr[0][0], positionArr[1][2]}, + new Vector2i[]{positionArr[0][0], positionArr[1][2]}); + + Voxel blueFlower1 = new Voxel(Index2, 1, + new Vector2i[]{positionArr[2][0], positionArr[2][0]}, + new Vector2i[]{positionArr[2][0], positionArr[2][0]}, + new Vector2i[]{positionArr[2][0], positionArr[2][0]}, + new Vector2i[]{positionArr[2][0], positionArr[2][0]}, + new Vector2i[]{positionArr[2][0], positionArr[2][0]}, + new Vector2i[]{positionArr[2][0], positionArr[2][0]}); + + Voxel blueFlower2 = new Voxel(Index2, 1, + new Vector2i[]{positionArr[2][1], positionArr[2][1]}, + new Vector2i[]{positionArr[2][1], positionArr[2][1]}, + new Vector2i[]{positionArr[2][1], positionArr[2][1]}, + new Vector2i[]{positionArr[2][1], positionArr[2][1]}, + new Vector2i[]{positionArr[2][1], positionArr[2][1]}, + new Vector2i[]{positionArr[2][1], positionArr[2][1]}); + + Voxel blueFlower3 = new Voxel(Index2, 1, + new Vector2i[]{positionArr[2][2], positionArr[2][2]}, + new Vector2i[]{positionArr[2][2], positionArr[2][2]}, + new Vector2i[]{positionArr[2][2], positionArr[2][2]}, + new Vector2i[]{positionArr[2][2], positionArr[2][2]}, + new Vector2i[]{positionArr[2][2], positionArr[2][2]}, + new Vector2i[]{positionArr[2][2], positionArr[2][2]}); + + Voxel blueFlower4 = new Voxel(Index2, 1, + new Vector2i[]{positionArr[2][3], positionArr[2][3]}, + new Vector2i[]{positionArr[2][3], positionArr[2][3]}, + new Vector2i[]{positionArr[2][3], positionArr[2][3]}, + new Vector2i[]{positionArr[2][3], positionArr[2][3]}, + new Vector2i[]{positionArr[2][3], positionArr[2][3]}, + new Vector2i[]{positionArr[2][3], positionArr[2][3]}); + + Voxel blueFlower5 = new Voxel(Index2, 1, + new Vector2i[]{positionArr[3][0], positionArr[3][0]}, + new Vector2i[]{positionArr[3][0], positionArr[3][0]}, + new Vector2i[]{positionArr[3][0], positionArr[3][0]}, + new Vector2i[]{positionArr[3][0], positionArr[3][0]}, + new Vector2i[]{positionArr[3][0], positionArr[3][0]}, + new Vector2i[]{positionArr[3][0], positionArr[3][0]}); + + Voxel blueFlower6 = new Voxel(Index2, 1, + new Vector2i[]{positionArr[3][1], positionArr[3][1]}, + new Vector2i[]{positionArr[3][1], positionArr[3][1]}, + new Vector2i[]{positionArr[3][1], positionArr[3][1]}, + new Vector2i[]{positionArr[3][1], positionArr[3][1]}, + new Vector2i[]{positionArr[3][1], positionArr[3][1]}, + new Vector2i[]{positionArr[3][1], positionArr[3][1]}); + + Voxel blueFlower7 = new Voxel(Index2, 1, + new Vector2i[]{positionArr[3][2], positionArr[3][2]}, + new Vector2i[]{positionArr[3][2], positionArr[3][2]}, + new Vector2i[]{positionArr[3][2], positionArr[3][2]}, + new Vector2i[]{positionArr[3][2], positionArr[3][2]}, + new Vector2i[]{positionArr[3][2], positionArr[3][2]}, + new Vector2i[]{positionArr[3][2], positionArr[3][2]}); + + Voxel blueFlower8 = new Voxel(Index2, 1, + new Vector2i[]{positionArr[3][3], positionArr[3][3]}, + new Vector2i[]{positionArr[3][3], positionArr[3][3]}, + new Vector2i[]{positionArr[3][3], positionArr[3][3]}, + new Vector2i[]{positionArr[3][3], positionArr[3][3]}, + new Vector2i[]{positionArr[3][3], positionArr[3][3]}, + new Vector2i[]{positionArr[3][3], positionArr[3][3]}); + Voxel blueLeaves1 = new Voxel(Index3, 2, + new Vector2i[]{positionArr[0][3], positionArr[0][3]}, + new Vector2i[]{positionArr[0][3], positionArr[0][3]}, + new Vector2i[]{positionArr[0][3], positionArr[0][3]}, + new Vector2i[]{positionArr[0][3], positionArr[0][3]}, + new Vector2i[]{positionArr[0][3], positionArr[0][3]}, + new Vector2i[]{positionArr[0][3], positionArr[0][3]}); + Voxel blueLeaves2 = new Voxel(Index3, 2, + new Vector2i[]{positionArr[1][3], positionArr[1][3]}, + new Vector2i[]{positionArr[1][3], positionArr[1][3]}, + new Vector2i[]{positionArr[1][3], positionArr[1][3]}, + new Vector2i[]{positionArr[1][3], positionArr[1][3]}, + new Vector2i[]{positionArr[1][3], positionArr[1][3]}, + new Vector2i[]{positionArr[1][3], positionArr[1][3]}); + + VoxelWorldManager.AddVoxel(grassVoxel, "grass");//1 + VoxelWorldManager.AddVoxel(stoneVoxel, "DirtVoxel");//2 + VoxelWorldManager.AddVoxel(stoneVoxel, "StoneVoxel");//3 + VoxelWorldManager.AddVoxel(grassSideVoxel, "grassSideVoxel");//4 + VoxelWorldManager.AddVoxel(Mushroom, "mushroom");//5 + VoxelWorldManager.AddVoxel(Log, "log");//6 + VoxelWorldManager.AddVoxel(Leaves, "leaves");//7 + VoxelWorldManager.AddVoxel(bluegrassVoxel, "bluegrassVoxel");//8 + VoxelWorldManager.AddVoxel(blueDirtVoxel, "blueDirtVoxel");//9 + VoxelWorldManager.AddVoxel(bluegrassSideVoxel, "bluegrassSideVoxel");//10 + VoxelWorldManager.AddVoxel(blueFlower1, "blueFlower1");//11 + VoxelWorldManager.AddVoxel(blueFlower2, "blueFlower2");//12 + VoxelWorldManager.AddVoxel(blueFlower3, "blueFlower3");//13 + VoxelWorldManager.AddVoxel(blueFlower4, "blueFlower4");//14 + VoxelWorldManager.AddVoxel(blueFlower5, "blueFlower5");//15 + VoxelWorldManager.AddVoxel(blueFlower6, "blueFlower6");//16 + VoxelWorldManager.AddVoxel(blueFlower7, "blueFlower7");//17 + VoxelWorldManager.AddVoxel(blueFlower8, "blueFlower8");//18 + VoxelWorldManager.AddVoxel(blueLeaves1, "blueLeaves1");//19 + VoxelWorldManager.AddVoxel(blueLeaves2, "blueLeaves2");//20 + + Biome GreenBiome = new Biome(1,2,3,4,new int[]{5,6,7,4},new int[]{4,4,4,4},new int[]{4,18,16,17}); + Biome Blueleaf = new Biome(8,9,3,10,new int[]{11,19,20,14},new int[]{5,6,7,8},new int[]{15,16,17,18}); + + VoxelWorldManager.AddBiome(Blueleaf, "blueleaf"); + VoxelWorldManager.AddBiome(GreenBiome, "greenBiome"); } public GuiRenderer GetGUIRenderer(){return GuiRender;} diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Main/GameCore.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Main/GameCore.java index b748b65..53ff5d8 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Main/GameCore.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Main/GameCore.java @@ -163,8 +163,14 @@ public class GameCore implements GameLogic { boolean createOfflinePlayer = !PrimaryRuntime.IsServer && !ClientSideNetworkUtils.Connected; MaterialData VoxelMat = new MaterialData("VoxelTerrain","resources/EngineResources/Texture/test_cube.png","","",new Vector4f(1,1,1,1), - 0,0,"",new Vector4f(),"",0,"",1,new Vector4f(),1.0f,0); + 0,0,"",new Vector4f(),"resources/EngineResources/Texture/test_cube_translucency.png",0,"",1,new Vector4f(),1.0f,0); + MaterialData BlueleafMat = new MaterialData("Blueleaf","resources/EngineResources/Texture/blueleaf_set.png","","",new Vector4f(1,1,1,1), + 0,0,"",new Vector4f(),"resources/EngineResources/Texture/blueleaf_set_translucent.png",0,"",1,new Vector4f(),1.0f,0); + MaterialData BlueleafMat2 = new MaterialData("Blueleaf2","resources/EngineResources/Texture/blueleaf_set_2.png","","",new Vector4f(1,1,1,1), + 0,0,"",new Vector4f(),"resources/EngineResources/Texture/blueleaf_set_2_translucent.png",0,"",1,new Vector4f(),1.0f,0); materials.add(VoxelMat); + materials.add(BlueleafMat); + materials.add(BlueleafMat2); materials.addAll(MelonaMat); materials.addAll(CollisionVisualisationMat); materials.addAll(MelonaMaterial); @@ -681,11 +687,11 @@ public class GameCore implements GameLogic { Vector3f CamRot = cam.GetRotation(); Vector3i ChunkPos = new Vector3i((int)Math.floor(CamPos.x/ (float) VoxelChunkGenerator.CHUNK_SIZE),(int)Math.floor(CamPos.y/ (float)VoxelChunkGenerator.CHUNK_SIZE),(int)Math.floor(CamPos.z/ (float)VoxelChunkGenerator.CHUNK_SIZE)); if(ChunkPos.x != VoxelWorldManager.LastPosition.x || ChunkPos.y != VoxelWorldManager.LastPosition.y || ChunkPos.z != VoxelWorldManager.LastPosition.z || CamRot.x != LastCamRotation.x || CamRot.y != LastCamRotation.y || CamRot.z != LastCamRotation.z) { - VoxelWorldManager.UnloadFarChunks(ChunkPos, 12,cam.GetViewMatrix(),projection.GetProjectionMatrix()); - VoxelWorldManager.GenerateChunks(ChunkPos, new Vector3i(12,8,12),cam.GetViewMatrix(),projection.GetProjectionMatrix()); + VoxelWorldManager.UnloadFarChunks(ChunkPos, 16,cam.GetViewMatrix(),projection.GetProjectionMatrix()); + VoxelWorldManager.GenerateChunks(ChunkPos, new Vector3i(16,16,16),cam.GetViewMatrix(),projection.GetProjectionMatrix()); } else { - VoxelWorldManager.UnloadFarChunks(ChunkPos, 24,cam.GetViewMatrix(),projection.GetProjectionMatrix()); - VoxelWorldManager.GenerateChunks(ChunkPos, new Vector3i(24,12,24),cam.GetViewMatrix(),projection.GetProjectionMatrix()); + VoxelWorldManager.UnloadFarChunks(ChunkPos, 96,cam.GetViewMatrix(),projection.GetProjectionMatrix()); + VoxelWorldManager.GenerateChunks(ChunkPos, new Vector3i(48,16,48),cam.GetViewMatrix(),projection.GetProjectionMatrix()); } LastCamRotation.set(CamRot); if(PrimaryRuntime.IsServer){ diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Main/PrimaryRuntime.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Main/PrimaryRuntime.java index 9b8ccd8..567f985 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Main/PrimaryRuntime.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Main/PrimaryRuntime.java @@ -163,9 +163,9 @@ CreateNewClientConnection(); Logger.debug("UnThrottlingEngine"); FrameAccuracy= OriginalFrameAccuracy; } - PrimaryThread.UpdateFrameAccuracy(); - DrawingThread.UpdateFrameAccuracy(); - FastThread.UpdateFrameAccuracy(); + if(PrimaryThread != null)PrimaryThread.UpdateFrameAccuracy(); + if(DrawingThread != null)DrawingThread.UpdateFrameAccuracy(); + if(FastThread != null)FastThread.UpdateFrameAccuracy(); } public void UpdateTickRateThreshold(){ CappedToTickRate = EngineConfig.getInstance().GetPrimaryTickCap(); diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Computing/VoxelTerrainGeneration/Biome.java b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Computing/VoxelTerrainGeneration/Biome.java new file mode 100644 index 0000000..6796a78 --- /dev/null +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Computing/VoxelTerrainGeneration/Biome.java @@ -0,0 +1,4 @@ +package net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Computing.VoxelTerrainGeneration; + +public record Biome(int surfaceBlock, int dirtBlock, int stoneBlock, int grassFoliage, int[] foliageBlocks, int[] tallBlocks, int[] otherFoliage) { +} diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Computing/VoxelTerrainGeneration/SharedVoxelTerrainResources.java b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Computing/VoxelTerrainGeneration/SharedVoxelTerrainResources.java index fc60b0d..24796f3 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Computing/VoxelTerrainGeneration/SharedVoxelTerrainResources.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Computing/VoxelTerrainGeneration/SharedVoxelTerrainResources.java @@ -8,8 +8,13 @@ import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Pipeline.P import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Shader.*; import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Structure.DeviceLayers.Device; import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Util.VulkanBuffer; +import org.lwjgl.system.MemoryUtil; import org.lwjgl.util.shaderc.Shaderc; +import java.nio.ByteBuffer; +import java.util.List; + +import static org.lwjgl.util.vma.Vma.VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT; import static org.lwjgl.util.vma.Vma.VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE; import static org.lwjgl.vulkan.VK13.*; @@ -22,20 +27,31 @@ public class SharedVoxelTerrainResources { public static final int TERRAIN_GENERATION_PUSH_CONSTANT_SIZE = Integer.BYTES * 8; + public static final int MAX_VOXEL_TYPES = 256; + public static final int MAX_BIOME_TYPES = 256; + public static final int VOXEL_REG_DATA_SIZE = 104; + public static final int BIOME_REG_DATA_SIZE = 64; + private static final String DESC_ID_VOXEL_GENERATION = "VOXEL_SHARED_DESC_GENERATION"; private static final String DESC_ID_RESET = "VOXEL_SHARED_DESC_RESET"; private static final String DESC_ID_MESH = "VOXEL_SHARED_DESC_MESH"; private static final String DESC_ID_FACE_GRAPHICS = "VOXEL_SHARED_DESC_FACE_GRAPHICS"; + private static final String DESC_ID_VOXEL_REG = "VOXEL_REGISTRY"; + private static final String DESC_ID_BIOME_REG = "BIOME_REGISTRY"; private final VoxelMeshPool meshPool; private final VulkanBuffer voxelData; private final VulkanBuffer counters; + private final VulkanBuffer voxelRegistryBuffer; + private final VulkanBuffer biomeRegistryBuffer; private final DescriptorSetLayout voxelGenerationLayout; private final DescriptorSetLayout resetLayout; private final DescriptorSetLayout meshGenerationLayout; private final DescriptorSetLayout faceGraphicsLayout; + private final DescriptorSetLayout voxelDeclarationLayout; + private final DescriptorSetLayout biomeDeclarationLayout; private static final String MESH_GENERATION_GLSL = "resources/EngineResources/VoxelComputeShaders/meshGenerationShared.glsl"; private static final String VOXEL_GENERATION_GLSL = "resources/EngineResources/VoxelComputeShaders/voxelGenerationShared.glsl"; @@ -58,6 +74,15 @@ public class SharedVoxelTerrainResources { counters = new VulkanBuffer(VkCtx, COUNTER_BUFFER_SIZE, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE, 0, 0); + voxelRegistryBuffer = new VulkanBuffer(VkCtx, (long) MAX_VOXEL_TYPES * VOXEL_REG_DATA_SIZE, + VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE, + VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); + biomeRegistryBuffer = new VulkanBuffer(VkCtx, (long) MAX_BIOME_TYPES * BIOME_REG_DATA_SIZE, + VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE, + VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); + voxelGenerationLayout = new DescriptorSetLayout(VkCtx, new DescriptorSetLayout.LayoutInformation[]{ new DescriptorSetLayout.LayoutInformation(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 0, 1, VK_SHADER_STAGE_COMPUTE_BIT) }); @@ -78,6 +103,13 @@ public class SharedVoxelTerrainResources { new DescriptorSetLayout.LayoutInformation(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,0,1,VK_SHADER_STAGE_VERTEX_BIT ) }); + voxelDeclarationLayout = new DescriptorSetLayout(VkCtx, new DescriptorSetLayout.LayoutInformation[]{ + new DescriptorSetLayout.LayoutInformation(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 0, 1, VK_SHADER_STAGE_COMPUTE_BIT) + }); + biomeDeclarationLayout = new DescriptorSetLayout(VkCtx, new DescriptorSetLayout.LayoutInformation[]{ + new DescriptorSetLayout.LayoutInformation(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 0, 1, VK_SHADER_STAGE_COMPUTE_BIT) + }); + createDescriptorSets(VkCtx); PushConstantsRange[] generationPushConstants = new PushConstantsRange[]{ @@ -90,9 +122,11 @@ public class SharedVoxelTerrainResources { resetPipeline = new ComputePipeline(VkCtx,resetShader,new DescriptorSetLayout[]{resetLayout},generationPushConstants); - voxelGenerationPipeline = new ComputePipeline(VkCtx,voxelShader, new DescriptorSetLayout[]{voxelGenerationLayout},generationPushConstants); + voxelGenerationPipeline = new ComputePipeline(VkCtx,voxelShader, + new DescriptorSetLayout[]{voxelGenerationLayout,biomeDeclarationLayout},generationPushConstants); - meshGenerationPipeline = new ComputePipeline( VkCtx,meshShader, new DescriptorSetLayout[]{meshGenerationLayout},generationPushConstants ); + meshGenerationPipeline = new ComputePipeline(VkCtx, meshShader, + new DescriptorSetLayout[]{meshGenerationLayout, voxelDeclarationLayout}, generationPushConstants); resetShader.CleanUp(VkCtx); voxelShader.CleanUp(VkCtx); @@ -126,6 +160,71 @@ public class SharedVoxelTerrainResources { DescriptorSet faceGraphicsSet = allocator.AddDescriptorSet(device, DESC_ID_FACE_GRAPHICS, faceGraphicsLayout); faceGraphicsSet.SetBuffer(device, meshPool.facePool(), meshPool.facePool().GetRequestedSize(), 0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER); + + DescriptorSet voxelDeclareDescriptorSet = allocator.AddDescriptorSet(device, DESC_ID_VOXEL_REG, voxelDeclarationLayout); + voxelDeclareDescriptorSet.SetBuffer(device, voxelRegistryBuffer, voxelRegistryBuffer.GetRequestedSize(), 0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER); + DescriptorSet biomeDeclareDescriptorSet = allocator.AddDescriptorSet(device, DESC_ID_BIOME_REG, biomeDeclarationLayout); + biomeDeclareDescriptorSet.SetBuffer(device, biomeRegistryBuffer, biomeRegistryBuffer.GetRequestedSize(), 0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER); + + } + + public void UploadBiomeRegistry(VulkanContext VkCtx, List biomeReg) { + int count = Math.min(biomeReg.size(), MAX_BIOME_TYPES); + long memoryAddr = biomeRegistryBuffer.MapMemory(VkCtx); + ByteBuffer buffer = MemoryUtil.memByteBuffer(memoryAddr, (int) biomeRegistryBuffer.GetRequestedSize()); + + for (int i = 0; i < count; i++) { + Biome biome = biomeReg.get(i); + int base = i * BIOME_REG_DATA_SIZE; + buffer.putInt(base + 0, biome.surfaceBlock()); + buffer.putInt(base + 4, biome.dirtBlock()); + buffer.putInt(base + 8, biome.stoneBlock()); + buffer.putInt(base + 12, biome.grassFoliage()); + for (int j = 0; j < 4; j++) { + buffer.putInt(base + 16 + j * 4, biome.foliageBlocks()[j]); + buffer.putInt(base + 32 + j * 4, biome.tallBlocks()[j]); + buffer.putInt(base + 48 + j * 4, biome.otherFoliage()[j]); + } + } + biomeRegistryBuffer.UnMapMemory(VkCtx); + } + + public void UploadVoxelRegistry(VulkanContext VkCtx, List voxelReg) { + int count = Math.min(voxelReg.size(), MAX_VOXEL_TYPES); + long memoryAddr = voxelRegistryBuffer.MapMemory(VkCtx); + ByteBuffer buffer = MemoryUtil.memByteBuffer(memoryAddr, (int) voxelRegistryBuffer.GetRequestedSize()); + + for (int i = 0; i < count; i++) { + Voxel voxel = voxelReg.get(i); + int base = i * VOXEL_REG_DATA_SIZE; + buffer.putInt(base + 0, voxel.MaterialID()); + buffer.putInt(base + 4, voxel.BlockType()); + buffer.putInt(base + 8, voxel.UpUV()[0].x); + buffer.putInt(base + 12, voxel.UpUV()[0].y); + buffer.putInt(base + 16, voxel.UpUV()[1].x); + buffer.putInt(base + 20, voxel.UpUV()[1].y); + buffer.putInt(base + 24, voxel.DownUV()[0].x); + buffer.putInt(base + 28, voxel.DownUV()[0].y); + buffer.putInt(base + 32, voxel.DownUV()[1].x); + buffer.putInt(base + 36, voxel.DownUV()[1].y); + buffer.putInt(base + 40, voxel.NorthUV()[0].x); + buffer.putInt(base + 44, voxel.NorthUV()[0].y); + buffer.putInt(base + 48, voxel.NorthUV()[1].x); + buffer.putInt(base + 52, voxel.NorthUV()[1].y); + buffer.putInt(base + 56, voxel.SouthUV()[0].x); + buffer.putInt(base + 60, voxel.SouthUV()[0].y); + buffer.putInt(base + 64, voxel.SouthUV()[1].x); + buffer.putInt(base + 68, voxel.SouthUV()[1].y); + buffer.putInt(base + 72, voxel.EastUV()[0].x); + buffer.putInt(base + 76, voxel.EastUV()[0].y); + buffer.putInt(base + 80, voxel.EastUV()[1].x); + buffer.putInt(base + 84, voxel.EastUV()[1].y); + buffer.putInt(base + 88, voxel.WestUV()[0].x); + buffer.putInt(base + 92, voxel.WestUV()[0].y); + buffer.putInt(base + 96, voxel.WestUV()[1].x); + buffer.putInt(base + 100, voxel.WestUV()[1].y); + } + voxelRegistryBuffer.UnMapMemory(VkCtx); } public DescriptorSetLayout faceGraphicsLayout() { @@ -163,6 +262,12 @@ public class SharedVoxelTerrainResources { public String voxelGenerationDescriptorId() { return DESC_ID_VOXEL_GENERATION; } + public String voxelRegDescriptorID() { + return DESC_ID_VOXEL_REG; + } + public String biomeRegDescriptorID() { + return DESC_ID_BIOME_REG; + } public String resetDescriptorId() { return DESC_ID_RESET; @@ -181,9 +286,13 @@ public class SharedVoxelTerrainResources { voxelGenerationLayout.CleanUp(VkCtx); meshGenerationLayout.CleanUp(VkCtx); faceGraphicsLayout.CleanUp(VkCtx); + voxelDeclarationLayout.CleanUp(VkCtx); + biomeDeclarationLayout.CleanUp(VkCtx); voxelData.cleanup(VkCtx); counters.cleanup(VkCtx); + voxelRegistryBuffer.cleanup(VkCtx); + biomeRegistryBuffer.cleanup(VkCtx); meshPool.cleanup(VkCtx); } } \ No newline at end of file diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Computing/VoxelTerrainGeneration/Voxel.java b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Computing/VoxelTerrainGeneration/Voxel.java new file mode 100644 index 0000000..c3a6e74 --- /dev/null +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Computing/VoxelTerrainGeneration/Voxel.java @@ -0,0 +1,6 @@ +package net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Computing.VoxelTerrainGeneration; + +import org.joml.Vector2i; + +public record Voxel(int MaterialID, int BlockType, Vector2i[] UpUV, Vector2i[] DownUV, Vector2i[] NorthUV, Vector2i[] SouthUV, Vector2i[] EastUV, Vector2i[] WestUV) { +} diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Computing/VoxelTerrainGeneration/VoxelChunkGenerator.java b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Computing/VoxelTerrainGeneration/VoxelChunkGenerator.java index 0430a45..e3698da 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Computing/VoxelTerrainGeneration/VoxelChunkGenerator.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Computing/VoxelTerrainGeneration/VoxelChunkGenerator.java @@ -38,16 +38,18 @@ public class VoxelChunkGenerator { pushConstants.putInt(8, chunk.position().z); pushConstants.putInt(12, chunk.slot()); pushConstants.putInt(16, faceOffset); - pushConstants.putInt(20, 0); + pushConstants.putInt(20, VoxelWorldManager.GetVoxelTypeCount()); pushConstants.putInt(24, indirectCommandIndex); - pushConstants.putInt(28, 0); + pushConstants.putInt(28, VoxelWorldManager.GetBiomeTypeCount()); LongBuffer resetDescriptorSet = stack.longs(allocator.GetDescriptorSet( resources.resetDescriptorId()).GetVkDescriptorSet()); LongBuffer voxelDescriptorSet = stack.longs(allocator.GetDescriptorSet( - resources.voxelGenerationDescriptorId()).GetVkDescriptorSet()); - LongBuffer meshDescriptorSet = stack.longs(allocator.GetDescriptorSet( - resources.meshDescriptorId()).GetVkDescriptorSet()); + resources.voxelGenerationDescriptorId()).GetVkDescriptorSet(), + allocator.GetDescriptorSet(resources.biomeRegDescriptorID()).GetVkDescriptorSet()); + LongBuffer meshDescriptorSet = stack.longs( + allocator.GetDescriptorSet(resources.meshDescriptorId()).GetVkDescriptorSet(), + allocator.GetDescriptorSet(resources.voxelRegDescriptorID()).GetVkDescriptorSet()); vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_COMPUTE,resources.resetPipeline().GetVulkanPipeline()); vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_COMPUTE,resources.resetPipeline().GetVulkanPipelineLayout(),0, resetDescriptorSet,null ); diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Computing/VoxelTerrainGeneration/VoxelWorldManager.java b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Computing/VoxelTerrainGeneration/VoxelWorldManager.java index ca06519..3510b02 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Computing/VoxelTerrainGeneration/VoxelWorldManager.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Computing/VoxelTerrainGeneration/VoxelWorldManager.java @@ -10,6 +10,8 @@ import org.lwjgl.vulkan.VkCommandBuffer; import org.tinylog.Logger; import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedQueue; @@ -17,7 +19,7 @@ import static org.lwjgl.vulkan.VK13.*; public class VoxelWorldManager { public static final int CHUNK_SIZE = 16; - private static final int MAX_RESIDENT_CHUNKS = 8192 * 2; + private static final int MAX_RESIDENT_CHUNKS = 8192 * 3; private static final int MAX_CHUNK_GENERATIONS_PER_FRAME = 128; private static final ConcurrentLinkedQueue RequestedChunks = new ConcurrentLinkedQueue<>(); @@ -25,6 +27,71 @@ public class VoxelWorldManager { private static final ConcurrentHashMap KnownChunks = new ConcurrentHashMap<>(); private static final ConcurrentHashMap CulledChunks = new ConcurrentHashMap<>(); + private static final List VoxelRegistry = new java.util.concurrent.CopyOnWriteArrayList<>(); + private static final ConcurrentHashMap VoxelNameToIndex = new ConcurrentHashMap<>(); + private static volatile boolean RegistryDirty = false; + + private static final List BiomeRegistry = new java.util.concurrent.CopyOnWriteArrayList<>(); + private static final ConcurrentHashMap BiomeNameToIndex = new ConcurrentHashMap<>(); + private static volatile boolean BiomeRegistryDirty = false; + + public static synchronized void AddVoxel(Voxel voxel, String name) { + Integer existing = VoxelNameToIndex.get(name); + if (existing != null) { + VoxelRegistry.set(existing, voxel); + } else { + VoxelNameToIndex.put(name, VoxelRegistry.size()); + VoxelRegistry.add(voxel); + } + RegistryDirty = true; + } + + public static List GetVoxelRegistry() { + return new ArrayList<>(VoxelRegistry); + } + + public static Voxel GetVoxel(String name) { + Integer idx = VoxelNameToIndex.get(name); + return idx == null ? null : VoxelRegistry.get(idx); + } + + public static int GetVoxelTypeID(String name) { + Integer idx = VoxelNameToIndex.get(name); + return idx == null ? -1 : idx + 1; + } + + public static int GetVoxelTypeCount() { + return VoxelRegistry.size(); + } + + public static synchronized void AddBiome(Biome biome, String name) { + Integer existing = BiomeNameToIndex.get(name); + if (existing != null) { + BiomeRegistry.set(existing, biome); + } else { + BiomeNameToIndex.put(name, BiomeRegistry.size()); + BiomeRegistry.add(biome); + } + BiomeRegistryDirty = true; + } + + public static List GetBiomeRegistry() { + return new ArrayList<>(BiomeRegistry); + } + + public static Biome GetBiome(String name) { + Integer idx = BiomeNameToIndex.get(name); + return idx == null ? null : BiomeRegistry.get(idx); + } + + public static int GetBiomeTypeID(String name) { + Integer idx = BiomeNameToIndex.get(name); + return idx == null ? -1 : idx + 1; + } + + public static int GetBiomeTypeCount() { + return BiomeRegistry.size(); + } private static SharedVoxelTerrainResources Resources; private static VoxelChunkGenerator Generator; @@ -59,7 +126,7 @@ public class VoxelWorldManager { public static int GenerationOffset = 0; public static Vector3i LastPosition = new Vector3i(0, 0, 0); - static int IterationX = 0; + static volatile int IterationX = 0; static Vector3i ChunkPos = new Vector3i(0, 0, 0); static Vector3i ChunkPos2 = new Vector3i(0, 0, 0); @@ -70,6 +137,11 @@ public class VoxelWorldManager { private static Vector3f min = new Vector3f(); private static Vector3f min2 = new Vector3f(); + public static synchronized void ResetIterationX() + { + IterationX = 0; + } + public static synchronized void GenerateChunks(Vector3i Position, Vector3i Radius, Matrix4f cameraView,Matrix4f projectionMatrix) { projectionMatrix.mul(cameraView, viewProjectionMatrix); @@ -118,6 +190,20 @@ public class VoxelWorldManager { Init(VkCtx); } + if (RegistryDirty) { + RegistryDirty = false; + Resources.UploadVoxelRegistry(VkCtx, GetVoxelRegistry()); + } + if (BiomeRegistryDirty) { + BiomeRegistryDirty = false; + Resources.UploadBiomeRegistry(VkCtx, GetBiomeRegistry()); + } + + if (VoxelRegistry.isEmpty()) { + return; // nothing to mesh against yet + } + + int generatedThisFrame = 0; while (!RequestedChunks.isEmpty() && generatedThisFrame < MAX_CHUNK_GENERATIONS_PER_FRAME) { @@ -206,19 +292,19 @@ public class VoxelWorldManager { KnownChunks.remove(pos); return true; } - int dx = pos.x - centerChunk.x; - int dy = pos.y - centerChunk.y; - int dz = pos.z - centerChunk.z; - - int distSq = dx * dx + dy * dy + dz * dz; - if (distSq > maxDistSq) { - RenderChunk chunk = entry.getValue(); - - Resources.meshPool().free(chunk); - KnownChunks.remove(pos); - - return true; - } +// int dx = pos.x - centerChunk.x; +// int dy = pos.y - centerChunk.y; +// int dz = pos.z - centerChunk.z; +// +// int distSq = dx * dx + dy * dy + dz * dz; +// if (distSq > maxDistSq) { +// RenderChunk chunk = entry.getValue(); +// +// Resources.meshPool().free(chunk); +// KnownChunks.remove(pos); +// +// return true; +// } return false; }); diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/RenderPasses/DeferredRendering/DeferredSceneRender.java b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/RenderPasses/DeferredRendering/DeferredSceneRender.java index 5fd0dd8..7cb942b 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/RenderPasses/DeferredRendering/DeferredSceneRender.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/RenderPasses/DeferredRendering/DeferredSceneRender.java @@ -82,6 +82,8 @@ public class DeferredSceneRender implements SceneRenderer {//dynamic rendering private static final String FRAGMENT_OPAQUE_SHADER_FILE_SPV = FRAGMENT_OPAQUE_SHADER_FILE_GLSL + ".spv"; private static final String VERTEX_SHADER_FILE_GLSL = "resources/EngineResources/shaders/scene_vertex.glsl"; private static final String VERTEX_SHADER_FILE_SPV = VERTEX_SHADER_FILE_GLSL + ".spv"; + private static final String PACKED_FRAGMENT_SHADER_FILE_GLSL = "resources/EngineResources/shaders/packed_scene_fragment_deferred.glsl"; + private static final String PACKED_FRAGMENT_SHADER_FILE_SPV = PACKED_FRAGMENT_SHADER_FILE_GLSL + ".spv"; private static final String PACKED_VERTEX_SHADER_FILE_GLSL = "resources/EngineResources/shaders/packed_scene_vertex.glsl"; private static final String PACKED_VERTEX_SHADER_FILE_SPV = PACKED_VERTEX_SHADER_FILE_GLSL + ".spv"; private Pipeline VkVoxelPipeline; @@ -246,11 +248,11 @@ public class DeferredSceneRender implements SceneRenderer {//dynamic rendering private static ShaderModule[] CreateShaderModules(VulkanContext VkCtx, int Translucent){ if(EngineConfig.getInstance().RecompileShaders()){ ShaderCompiler.CompileGLSLShaderOnChange(Translucent > 2 ? PACKED_VERTEX_SHADER_FILE_GLSL : VERTEX_SHADER_FILE_GLSL, Shaderc.shaderc_glsl_vertex_shader); - ShaderCompiler.CompileGLSLShaderOnChange( Translucent == 2 ? FRAGMENT_TRANSLUCENT_SHADER_FILE_GLSL : Translucent == 1 ? FRAGMENT_OPAQUE_SHADER_FILE_GLSL : FRAGMENT_SHADER_FILE_GLSL, Shaderc.shaderc_glsl_fragment_shader); + ShaderCompiler.CompileGLSLShaderOnChange( Translucent > 2 ? PACKED_FRAGMENT_SHADER_FILE_GLSL : Translucent == 2 ? FRAGMENT_TRANSLUCENT_SHADER_FILE_GLSL : Translucent == 1 ? FRAGMENT_OPAQUE_SHADER_FILE_GLSL : FRAGMENT_SHADER_FILE_GLSL, Shaderc.shaderc_glsl_fragment_shader); } return new ShaderModule[]{ new ShaderModule(VkCtx, VK_SHADER_STAGE_VERTEX_BIT, Translucent > 2 ? PACKED_VERTEX_SHADER_FILE_SPV :VERTEX_SHADER_FILE_SPV,null), - new ShaderModule(VkCtx, VK_SHADER_STAGE_FRAGMENT_BIT, Translucent == 2 ? FRAGMENT_TRANSLUCENT_SHADER_FILE_SPV : Translucent == 1 ? FRAGMENT_OPAQUE_SHADER_FILE_SPV : FRAGMENT_SHADER_FILE_SPV,null) + new ShaderModule(VkCtx, VK_SHADER_STAGE_FRAGMENT_BIT, Translucent > 2 ? PACKED_FRAGMENT_SHADER_FILE_SPV : Translucent == 2 ? FRAGMENT_TRANSLUCENT_SHADER_FILE_SPV : Translucent == 1 ? FRAGMENT_OPAQUE_SHADER_FILE_SPV : FRAGMENT_SHADER_FILE_SPV,null) }; } diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/RenderPasses/Forward/ForwardSceneRender.java b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/RenderPasses/Forward/ForwardSceneRender.java index 18c6c6c..2441f62 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/RenderPasses/Forward/ForwardSceneRender.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/RenderPasses/Forward/ForwardSceneRender.java @@ -66,6 +66,8 @@ public class ForwardSceneRender implements SceneRenderer {//dynamic rendering public static String SkyBoxID = "SKYBOX_TEXTURE"; private static final int PUSH_CONSTANTS_SIZE = VulkanUtils.MATRIX4X4_SIZE + VulkanUtils.INT_SIZE; private final VulkanBuffer BufferProjectionMatrix; + private static final String PACKED_FRAGMENT_SHADER_FILE_GLSL = "resources/EngineResources/shaders/packed_scene_fragment.glsl"; + private static final String PACKED_FRAGMENT_SHADER_FILE_SPV = PACKED_FRAGMENT_SHADER_FILE_GLSL + ".spv"; private static final String PACKED_VERTEX_SHADER_FILE_GLSL = "resources/EngineResources/shaders/packed_scene_vertex.glsl"; private static final String PACKED_VERTEX_SHADER_FILE_SPV = PACKED_VERTEX_SHADER_FILE_GLSL + ".spv"; private Pipeline VkVoxelPipeline; @@ -293,11 +295,11 @@ public class ForwardSceneRender implements SceneRenderer {//dynamic rendering private static ShaderModule[] CreateShaderModules(VulkanContext VkCtx, int Translucent){ if(EngineConfig.getInstance().RecompileShaders()){ ShaderCompiler.CompileGLSLShaderOnChange(Translucent > 2 ? PACKED_VERTEX_SHADER_FILE_GLSL :VERTEX_SHADER_FILE_GLSL, Shaderc.shaderc_glsl_vertex_shader); - ShaderCompiler.CompileGLSLShaderOnChange( Translucent == 2 ? FRAGMENT_TRANSLUCENT_SHADER_FILE_GLSL : Translucent == 1 ? FRAGMENT_OPAQUE_SHADER_FILE_GLSL : FRAGMENT_SHADER_FILE_GLSL, Shaderc.shaderc_glsl_fragment_shader); + ShaderCompiler.CompileGLSLShaderOnChange(Translucent > 2 ? PACKED_FRAGMENT_SHADER_FILE_GLSL : Translucent == 2 ? FRAGMENT_TRANSLUCENT_SHADER_FILE_GLSL : Translucent == 1 ? FRAGMENT_OPAQUE_SHADER_FILE_GLSL : FRAGMENT_SHADER_FILE_GLSL, Shaderc.shaderc_glsl_fragment_shader); } return new ShaderModule[]{ new ShaderModule(VkCtx, VK_SHADER_STAGE_VERTEX_BIT, Translucent > 2 ? PACKED_VERTEX_SHADER_FILE_SPV : VERTEX_SHADER_FILE_SPV,null), - new ShaderModule(VkCtx, VK_SHADER_STAGE_FRAGMENT_BIT, Translucent == 2 ? FRAGMENT_TRANSLUCENT_SHADER_FILE_SPV : Translucent == 1 ? FRAGMENT_OPAQUE_SHADER_FILE_SPV : FRAGMENT_SHADER_FILE_SPV,null) + new ShaderModule(VkCtx, VK_SHADER_STAGE_FRAGMENT_BIT,Translucent > 2 ? PACKED_FRAGMENT_SHADER_FILE_SPV : Translucent == 2 ? FRAGMENT_TRANSLUCENT_SHADER_FILE_SPV : Translucent == 1 ? FRAGMENT_OPAQUE_SHADER_FILE_SPV : FRAGMENT_SHADER_FILE_SPV,null) }; diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Structure/DeviceLayers/Device.java b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Structure/DeviceLayers/Device.java index 3cd6bd7..91c9b2b 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Structure/DeviceLayers/Device.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Structure/DeviceLayers/Device.java @@ -54,6 +54,7 @@ public class Device { } var features12 = VkPhysicalDeviceVulkan12Features.calloc(MemStack) .sType$Default() + .shaderSampledImageArrayNonUniformIndexing(true) .scalarBlockLayout(true); var features13 = VkPhysicalDeviceVulkan13Features.calloc(MemStack)