From 0074bf1d1f67c027c46efe269ff938144a543420 Mon Sep 17 00:00:00 2001 From: Halbear Date: Thu, 17 Sep 2026 21:48:04 +0100 Subject: [PATCH] voxel texture mapping --- .../EngineResources/Texture/test_cube.png | Bin 1567 -> 5321 bytes .../meshGenerationShared.glsl | 88 +++++++++++++++--- .../voxelGenerationShared.glsl | 21 +++-- .../shaders/packed_scene_vertex.glsl | 87 +++++++++++------ .../Terrain4J/EngineCore/Main/GameCore.java | 23 ++--- .../VoxelWorldManager.java | 21 +++-- .../RenderPasses/Lighting/LightRenderer.java | 2 - 7 files changed, 165 insertions(+), 77 deletions(-) diff --git a/resources/EngineResources/Texture/test_cube.png b/resources/EngineResources/Texture/test_cube.png index bc5571f8c18b96acf0ebebba3a2b30597e34956d..ee50980f8be2197d781a12cc1d3fb1ef64e0b19a 100644 GIT binary patch literal 5321 zcmW-l1zeL~7snr9Fp!2(V~imUN(x9QjdYA23OEt?lOt3Ri4l$tl@O3FrIC`7mKH=n zQW}wv6zTWj{d~5a`)qsex%Zy)``&Y(2t)mQ)YstG005xY(o{o(R_W?ZP6mE{_|Ibw zG(=wLdn!QL5MmtwU?Ey+$|gSPgI0bx6VueoS^Z6KvABRdPL^M-uf8~9!|AT`rNUKE z8cNLVx_U`f_idIw@K`1Bx>3u~TWXj~b~NzaExdNq!CW;)!OZ9psylU{^I=*N1wKd% z$1DCfZHPo=lqcgn_f%f?=qW!w@%?PM(3t<9J9S=xKaWl`{4q{0AMExeRskUPFO_Po zqqyiJnwMuwINuJ7q(UeVP}0)!@VG;)*X(}bC=nn+P(d9R6tVynVxla77y~&m5RBvm zP-F42R^#KEbapoTWM&V%P^$>QWC9UiJ63L6r5@EVWhOW`)gmKrF{Ju9(n~U8b+*~T zquPO0^}+)HI9^j7e;L{77OZbtNZHup5Q!$e2lm{qxJ(RyPCXv8me_+Y8iiRqrG{Q0 zWQ+=6rHsYlPE%znhLYg+qZ|J&-M~qJ*J8WAq*2>+x<90KnJ&5ON6e(g}S$=yu&cLz_|9 z>W0TjF<`Eu)0iB>GY=SA^DP~i69wdsq(nbE%2+v|srTQZqFPAHu#ScV-=|>Pw@a}T z)~!kuzCOQ)Q@`Y!b%xrNf>@qoQA zI@APx!EJwwuLGMwQtpljJAUr{4$=L|i^a&AFLz^E?ArdJ;~yM;{N066YkBk8_s_&e zfwVS}0!C?hE4TQWvs8tyD*a+e;(*rcbTSJ{z=7&)OM<_2Ee_Y0@rAqrd;&FFj- z{&J2rrq?3z3BOAfX`1_N=(EcvmOR8{j=CQqO7h`;X&L|=zh_dYNU)GxQwC=eN&fuB z3@JkmCJ+9NC`ecn@_iEBA!p@e@xZlMO_yf^CTO6YJt3u6oKJKKYrV2@&a@t+2`jHx zf8*90>GWMP8wx6WnR}RTf)lCeW!{{+gqsJCuxjDEqaF*0z8;xdP}xdt+}+MRT3ohZ zcd6p#Yc~#JoJ5^8Y1Ou;%Es9gYAP;s5=ck*zA?T~xkazBtYE_TU*C9H zdwbLUA9j?{EdBAB7(BcC5EQst@4|GwT9jf9F*LR*_U!vLP#g6%i%;zaURQ#wnc^wE zPW_6ZXNq#)GodI3NF^s6r(UhG6et(hLt$1@X(61zFH;aYNh|BJhw2ktEWgh6BPjyB zV_Jn19`SRZPwi!{wy~gsMw?Q| z;kl(wzptL?_;K~i89YqY88g)^Ffg(7i6c`-)RfcylNXzWWGkM;u$~BSF3e|CogtSW z0}1Zw?T;Y(Kz3*JoG2N}Hz~Ju9xnYb$NgFDcQHT!%mGlz@i#GZfglbvCbV!nkXsA~ z7F0NTg?e@|I^jHghA1nZt~A+ALLipEJ;9cVc7XPiqGY++^^>RvbMb))^+}C4W>Whb z5FZffAYz#%ru6hBk=E*~BN3*x1t9zvgIZ zMQInOme(J}@>2`%|M0l<{in*&4cfW|zNF(VT0Z4XIff zoA6wdKx}hBfK8`nn^!$Q7xB!eu4v-k8g%O_vAo|&+cW?y>{ARE=ng$M`1gW1;A0_) z<+|Lj!E%*6X)*Ob4@!^r9sHU+W%_k{Awa-Z{_hUmN79o-K_QIFERWflsKfnkcQUO| zs#R-VYrOJ;B^zIP~~(SlS5du?B1{I@$Vs7Pj@Zg{bXN7HDO5QYDS zSeKAT{4Ms}QXqER#@gVPmd}@p{*4@p}QcWdX_Uzb?r`d*Zqy)-&pdM(*CaORyqhYI_rC?U=mTa44V52b&p)ea8@bD6D7CA@t_;Yo_gB?{V>^p7Mk zl*S6k_w0c&3u{c#dwL*StFMTEy8zb$hZZPWrBrO7(^$?`uh}XCkWh z+I-0JnbHace1SP8mrM9{7e&R?8fBFyjCKo2)5gN8rtcA=wvD=0sp_vcNTrH~XkuP5 zPrcCsM1`G)ojiZ`2qb)je(k_ljMVo<1I*pDJ)xULf(f{U|M~QuuZ!`hy=G@_6+**eVs`-~=ekmjl9(*mdGDu=E=EC3muGcx0 z{k1ajP_|YAp54U=uQb0YYC?r!6#Vgt@Q6LfM^Iv}5_I2Ppk46SKUoIx`e@8Usf0ve z3d|tiEN`tz?$IZy$0BtFLR1WdDJ^ps7bhhJb9KJ^RVOeWT5_t zSOPn$FN=58L`l;ZORqL=VDqNCd?XX2cA23?5nhEK;#JAogR!ezqb%NlM6!dD7@jaa z$QE&D&9500XXg4`NJQ}2lJS#UtZjjC;)W$wcNzxPq=b9fF;1{<=p%$;O2+F|{r{RrP$jG*`PZ0tWCmKn}n`#O7WE{DXe( zQW?FoLmLof6sYLf5!}z-ZT$5O$+`jdG9xCPsq>{X*WMw91{R#CKI~KwE+W3yd#dY+ zBrI=sSJf1A$u=@&{=qfw9(B|$W|R=>{cxm!lGU^sxK#`EoEd<|Cwq4-k`~2_*kaSz zN-{9=ytgdh=G+DtQE5@kG&FQV)OAq>zZe)RJX@@@#emx&%nbEoe)g=> zDl;2DV6hB-OwCui+>Yj`-WPCsGds@FT9%Ku1n7^@Xfv0rp@dV{@(Uy_ICz|;Equ| zwpeP<;Uk`j2@E;+lgo?u+7$xRJ^p^y-H6s>ovW&ztiI{tjb_2HFA=g6N2rlh=;g%E zp=(W`sJfh^vYp!fRc$gVi9lcq<57Krh5y#tM$dFUTdeE7o zB)-_9z-}JeLsgmPzc!F&s~%P9vgJf`@lMixv86H6=#A?YtUj!SDU|V|jZ~SCrvA%h z26v2OZSG9R7G?;3X+X2rHT1A1%S3}nNiv>6(c_*ZvWn7N)n{=wciRN@+T2!NG`Dkr z3akM0!ZO(LH&56|QOx*6wrTc!O`4m%QXW|m#=1!JCtNOT@ul`$jtlosKAricK@!w0 zwv>V{CeBzGPeWMBo_7QVg6DD2e17kL57f?&oh%#I?aflk*W^bqvEIrvZiU$lKU}Ih z3MO_D25S*QQ2E)9LnLB@|DrG}>#$JAzENI2Tr0NOVBK(&5@ixG+FN_Vq zuV=BP)fRHrV`8am`m;*m4w!qepNNP*OT8{q!J=Y48&u*y62fzG_M`9Wcy;THj=-HW zKE~GOQngR8!s>VR9X}_XAMS+NV#x#}W;&m64LIO)s!kDBZyThLV8@avhDBT`9asmfWF zHbv{Mu;4?QI(Bu=rd&t+?<#{aAg1OOFA|=G$#4vYP1+I8SEjl3UQJWaN>ajHz8TWP z+yj9@5|F9U!DTB7wsIam*Nw4jCw@R%m6Mj=a{`ZSW5V8eseqq+^3SzTOV>Rk+4Jh| zdbeKeZB=}J;ivmMwoy^3T8@Kr(|gJBYXvs2)h3OI2jVElHf#A6T(tJkLTKamW@~O( z*p)uO+y7Na7uG9B%G`=+RJ48Y-gU|sh`3Gr&$-8emv?i4J5#9ji&sea<+I!$PU>Hp zn|-P)=wLenH_e^R|UnBh-<7D8BoH7eQbZa46ETp~9f zzqOh>JU{aJTVu0yc+)^AcJ$9#FVnfrA)n3%#vYD5P*}|6ydr(lLVPOV1Dq%M(iy~p zDffj*UznlW5lC8Oz>2!Ueh;IC=)HiPeZ27A$9IQS(bzODQT}Z5@atv9 z*MsnrgJRyd*17Zh7o{|{R?_>kd>h)_i5zUDPQKt47+putZUR;M0pZ=I%{p%ccE$-b z7Y3c@MCRALYo);d>#zju8lU|;`rOSJ_>aRbhO9~>@8BD=ul*KkUz_cjh*GmkPYc4@sx$q&o!^NNW@wL2vYreyvvw3bhZ;HyuQS z_&v>j(vCQd3m86+(MuF}t;E3ggC_q%JJX;_Qj9Qu#oupjo1p32ZDe=a69LTDf4Z_p@e*25zV?;d#mhYI8 Y$=}`K!(T&2@Yy7wrLM15reYiXKNYa$6aWAK literal 1567 zcmV+)2H^RLP)Px)*-1n}R9J}7`4(eq0TU?k40m%D7{adg8 zo@g?Gs_Ou>9S0%btv>)@YUT_8qBBsNP6|RmUj91*`MN56zY{K=BR}~5WpV@(Cu{aDGJ8OFwKU8ZW{9N zDGE-lPRnWHpF2OX*h3*1*SNK`%eAYM+*;Zt7Bg8{%@T{599CU6?ibOGA-X;2p|G-= z<=WLrY<&i&R!7xToO%OQQ|Wd(sJf1-sWcl7omPuRwMM(umLx)U6rZBtfBWqpE#6++ zCl)jLZo5h**TOJVdMI>zuyMbLVW^}p*xX**$1qfehgG^g_|Mt_zrFr0rF?;Exk9a6 zp;9d2QxsH9Mb&l8QHvo%$FxSMl@DoDYc#4gOlt()H1Kznp~XnVkbrZk5V^d=&h8=U z3pR&Um$_7kmDMbfh(X*o`R0B>>fZRp>xAqmm0}6kb#Yynw$qelQ8iWeglUb?ZnaVT zewq!3X2U_bapgL5sSw}XFA%p)Qq}?hH?CY~Wi=~}e>tB7AQ{()L<~~a0&}SlK1CsrvKAOi#vwb;IycGgw`3nIoOuU;N5(3V#ynY;vBE)?AAG{^ z-ufdfBNt1n*#eN|P<6epG-CPe{r7(aG)@+WWTGKkIp&c$s_eJFUk}c9gS|*!#BDR(f7XgP%+x;e;)n0J4(@iF{xC zK-c{jx9@B+7Sh=(Ir2>4@r#**I^!`D!`0cVIGme4O}?;0I5a_Se}|vF{x=^d5G7yO zc?t^bl^ik$bqOxcf?U3^a}vB~3E0sI0LDUkA1J{2QxU|kB|%OQeNjY|d|?MWIw2zz zfZnLbW9E?r1^E*Z0Jyug+4s;JHBYi5B0qmBBClVBC?ZM`u>kZ&4RCJybf4i~$$24V zP`oJ>fP$1Aosel3V1lHV@JS@#O{oC>^5LT=>c^mVbOJFgfYf`*A6JwwA3kC%q;vjM zq)#F0F2Ds5J38^qyC;!=*V(!0(=2`QHF%;N3q1wDyR|77llXITQc>`XQ@*gnc+8X$ zj>k+{p1WI{eWU0d*%J{EDHbHoO`m43S3Z6IDVj+2#)KP2s*aYb7`2IySm~wFz{qiEl@&6=f9yC0T RLj(W-002ovPDHLkV1gdC@1g(z diff --git a/resources/EngineResources/VoxelComputeShaders/meshGenerationShared.glsl b/resources/EngineResources/VoxelComputeShaders/meshGenerationShared.glsl index 95ea105..0ed1040 100644 --- a/resources/EngineResources/VoxelComputeShaders/meshGenerationShared.glsl +++ b/resources/EngineResources/VoxelComputeShaders/meshGenerationShared.glsl @@ -52,14 +52,68 @@ uint getVoxel(ivec3 pos) { return voxels[flatten(pos)]; } +uint hash21(uvec2 p) { + p = p * 1664525u + 1013904223u; + p.x += p.y * 1664525u; + p.y += p.x * 1664525u; + return p.x ^ (p.x >> 16); +} -uint packFace(uvec3 voxelPos, uint faceIndex, uint materialId, uint ao) { - return (voxelPos.x & 0x1Fu) | - ((voxelPos.y & 0x1Fu) << 5u) | - ((voxelPos.z & 0x1Fu) << 10u) | - ((faceIndex & 0x7u) << 15u) | - ((materialId & 0xFFu) << 18u) | - ((ao & 0x3u) << 26u); +uint random_1_to_3(vec2 uv, uint customSeed) { + uvec2 p = uvec2(floatBitsToUint(uv.x), floatBitsToUint(uv.y)); + p.x ^= customSeed; + uint randInt = hash21(p); + return (randInt % 3u) + 1u; +} + +uint packFace(uvec3 voxelPos, uint faceIndex, uint materialId) { + uint randomFaceValue = random_1_to_3(vec2(voxelPos.x, voxelPos.z),faceOffset); + uint textureIndexX = 0u; + uint textureIndexY = 0u; + if(materialId == 1u){ + if(faceIndex == 0u){ + textureIndexX = 0u; + textureIndexY = randomFaceValue; + } else if(faceIndex == 1u){ + textureIndexX = 1u; + textureIndexY = 0u; + } + else{ + textureIndexX = 0u; + textureIndexY = 0u; + } + } else if(materialId == 2u){ + textureIndexX = 1u; + textureIndexY = 0u; + }else if(materialId == 3u){ + textureIndexX = 1u; + textureIndexY = 0u; + }else if(materialId == 4u){ + textureIndexX = 1u; + textureIndexY = randomFaceValue; + }else if(materialId == 5u){ + textureIndexX = 2u; + textureIndexY = 3u; + }else if(materialId == 5u){ + if (faceIndex == 0u || faceIndex == 1u){ + textureIndexX = 2u; + textureIndexY = 1u; + } else{ + textureIndexX = 2u; + textureIndexY = 2u; + } + }else if(materialId == 6u){ + textureIndexX = 2u; + textureIndexY = 0u; + } + + return (voxelPos.x & 0x1Fu) | + ((voxelPos.y & 0x1Fu) << 5u) | + ((voxelPos.z & 0x1Fu) << 10u) | + ((faceIndex & 0x7u) << 15u) | + ((materialId & 0xFFu) << 18u) | + ((textureIndexX & 0x7u) << 26u) | + ((textureIndexY & 0x7u) << 29u); } void emitFace(ivec3 voxelPos, uint faceIndex, uint voxelType) { @@ -69,7 +123,7 @@ void emitFace(ivec3 voxelPos, uint faceIndex, uint voxelType) { return; } - faces[faceOffset + localFace] = packFace(uvec3(voxelPos), faceIndex, voxelType, 0u); + faces[faceOffset + localFace] = packFace(uvec3(voxelPos), faceIndex, voxelType); atomicAdd(drawCmds[indirectCommandIndex].vertexCount, VERTICES_PER_FACE); } @@ -87,10 +141,16 @@ void main() { return; } - if (getVoxel(pos + ivec3( 0, 1, 0)) == 0u) emitFace(pos, 0u, current); - if (getVoxel(pos + ivec3( 0, -1, 0)) == 0u) emitFace(pos, 1u, current); - if (getVoxel(pos + ivec3( 1, 0, 0)) == 0u) emitFace(pos, 2u, current); - if (getVoxel(pos + ivec3(-1, 0, 0)) == 0u) emitFace(pos, 3u, current); - if (getVoxel(pos + ivec3( 0, 0, 1)) == 0u) emitFace(pos, 4u, current); - if (getVoxel(pos + ivec3( 0, 0, -1)) == 0u) emitFace(pos, 5u, current); + if (current == 4u) { + 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); } \ No newline at end of file diff --git a/resources/EngineResources/VoxelComputeShaders/voxelGenerationShared.glsl b/resources/EngineResources/VoxelComputeShaders/voxelGenerationShared.glsl index 493f74c..66011bb 100644 --- a/resources/EngineResources/VoxelComputeShaders/voxelGenerationShared.glsl +++ b/resources/EngineResources/VoxelComputeShaders/voxelGenerationShared.glsl @@ -101,7 +101,6 @@ bool isCave(vec3 worldPos) { void main() { ivec3 localPos = ivec3(gl_GlobalInvocationID.xyz); ivec3 worldPos = chunkPos * CHUNK_SIZE + localPos; - float YZone = floor(worldPos.y/150.0)*150.0; float islandheight = 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 height = 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; @@ -109,6 +108,7 @@ void main() { float YZone2 = floor(worldPos.y/75.0)*75.0; float islandheight2 = valueNoise(vec2(worldPos.x - YZone2 * 2, worldPos.z -YZone2 * 2) * 0.005) * 60 + valueNoise(vec2(worldPos.x + YZone2 * 2, worldPos.z + YZone2 * 2) * 0.1) * 20 + valueNoise(vec2(worldPos.x + YZone2 * 2, worldPos.z + YZone2 * 2) * 0.1) * 10+ valueNoise(vec2(worldPos.x + YZone2 * 2, worldPos.z + YZone2 * 2)) * 0.5 - 5 + YZone2; float height2 = valueNoise(vec2(worldPos.x + YZone2 * 2, worldPos.z + YZone2 * 2) * 0.005) * 50 + valueNoise(vec2(worldPos.x + YZone2 * 2, worldPos.z + YZone2 * 2) * 0.01) * 10 + valueNoise(vec2(worldPos.x + YZone2 * 2, worldPos.z + YZone2 * 2) * 0.1) * 5+ valueNoise(vec2(worldPos.x + YZone2 * 2, worldPos.z + YZone2 * 2)) * 0.5 + YZone2; + float grassNoise = valueNoise(vec2(worldPos.z + YZone * 2, worldPos.x + YZone * 2)); //float height2 = valueNoise(vec2(-worldPos.x, -worldPos.z) * 0.005) * 100 + valueNoise(vec2(-worldPos.x, -worldPos.z) * 0.01) * 10 + valueNoise(vec2(-worldPos.x, -worldPos.z) * 0.1) * 5+ valueNoise(vec2(-worldPos.x, -worldPos.z)) * 0.5 + 100; //float islandheight2 = 100 + valueNoise(vec2(-worldPos.z, -worldPos.x) * 0.005) * 100 + valueNoise(vec2(-worldPos.x, -worldPos.z) * 0.1) * 20 + valueNoise(vec2(worldPos.x, worldPos.z) * 0.1) * 5+ valueNoise(vec2(worldPos.x, worldPos.z)) * 0.5 - 5; @@ -117,10 +117,12 @@ void main() { if (float(worldPos.y) <= height && float(worldPos.y) >= islandheight) { float depthBelowSurface = height - float(worldPos.y); - - if (depthBelowSurface < 1.5) { + if (depthBelowSurface < 0.5) { + if(grassNoise < 0.65) voxelType = 4u; // Grass foliage + else voxelType = 0u; + }else if (depthBelowSurface < 2.5) { voxelType = 1u; // Grass - } else if (depthBelowSurface < 5.0) { + } else if (depthBelowSurface < 6.0) { voxelType = 2u; // Dirt(also stone rn) } else { voxelType = 3u; // Stone @@ -129,10 +131,13 @@ void main() { else if (float(worldPos.y) <= height2 && float(worldPos.y) >= islandheight2) { float depthBelowSurface = height2 - float(worldPos.y); - if (depthBelowSurface < 1.5) { - voxelType = 1u; // Grass/topsoil - } else if (depthBelowSurface < 5.0) { - voxelType = 2u; // Dirt + if (depthBelowSurface < 0.5) { + if(grassNoise < 0.65) voxelType = 4u; // Grass foliage + else voxelType = 0u; + }else if (depthBelowSurface < 1.5) { + voxelType = 1u; // Grass + } else if (depthBelowSurface < 6.0) { + voxelType = 2u; // Dirt(also stone rn) } else { voxelType = 3u; // Stone } diff --git a/resources/EngineResources/shaders/packed_scene_vertex.glsl b/resources/EngineResources/shaders/packed_scene_vertex.glsl index 61b5eda..6e125f4 100644 --- a/resources/EngineResources/shaders/packed_scene_vertex.glsl +++ b/resources/EngineResources/shaders/packed_scene_vertex.glsl @@ -23,47 +23,67 @@ layout(push_constant) uniform pc { const uint TRI_TO_CORNER[6] = uint[6](0u, 1u, 2u, 0u, 2u, 3u); -const vec3 NORMALS[6] = vec3[6]( - vec3( 0.0, 1.0, 0.0), - vec3( 0.0, -1.0, 0.0), - vec3( 1.0, 0.0, 0.0), - vec3(-1.0, 0.0, 0.0), - vec3( 0.0, 0.0, 1.0), - vec3( 0.0, 0.0, -1.0) +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[6] = vec3[6]( - vec3( 1.0, 0.0, 0.0), - vec3( 1.0, 0.0, 0.0), - vec3( 0.0, 0.0, -1.0), - vec3( 0.0, 0.0, 1.0), - vec3( 1.0, 0.0, 0.0), - vec3(-1.0, 0.0, 0.0) +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[6] = vec3[6]( - vec3( 0.0, 0.0, 1.0), - vec3( 0.0, 0.0, -1.0), - vec3( 0.0, 1.0, 0.0), - vec3( 0.0, 1.0, 0.0), - vec3( 0.0, 1.0, 0.0), - vec3( 0.0, 1.0, 0.0) +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[16] = vec2[16]( - vec2(0.5, 0.0), vec2(0.5, 0.5), vec2(1.0, 0.5), vec2(1.0, 0.0), - vec2(0.0, 0.5), vec2(0.0, 1.0), vec2(0.5, 1.0), vec2(0.5, 0.5), - vec2(0.5, 0.0), vec2(0.5, 0.5), vec2(1.0, 0.5), vec2(1.0, 0.0), - vec2(0.5, 0.0), vec2(0.5, 0.5), vec2(1.0, 0.5), vec2(1.0, 0.0) +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[6][4] = vec3[6][4]( +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, 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) ); void main() { @@ -84,9 +104,14 @@ void main() { uint voxelZ = (packedFace >> 10u) & 0x1Fu; uint faceId = (packedFace >> 15u) & 0x7u; uint matId = (packedFace >> 18u) & 0xFFu; + uint texIdxX = (packedFace >> 26u) & 0x7u; + uint texIdxY = (packedFace >> 29u) & 0x7u; - faceId = min(faceId, 5u); - matId = min(matId, 3u); + vec2 texID = vec2((texIdxX)/4.0,(texIdxY)/4.0); + 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; @@ -99,5 +124,5 @@ void main() { outNormal = NORMALS[faceId]; outTangent = TANGENTS[faceId]; outBitangent = BITANGENTS[faceId]; - outTextCoords = CORNER_UVS[cornerIndex + (matId << 2u)]; + outTextCoords = CORNER_UVS_GRASS_BLOCK[faceId][cornerIndex] * scalar + texID; } \ No newline at end of file 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 6f3b29d..6ea59bc 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Main/GameCore.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Main/GameCore.java @@ -656,22 +656,12 @@ public class GameCore implements GameLogic { return imGuiIO.getWantCaptureKeyboard(); } Vector3f CamPos = new Vector3f(); + Vector3f LastCamRotation = new Vector3f(); @Override public void Update(EngineInstance engineInstance, long FrameDiffNanoSeconds) { if(!PrimaryRuntime.IsServer && !RenderThread.Headless) { Camera cam = engineInstance.scene().GetCamera(); - Project3D projection = engineInstance.scene().GetProjection(); CamPos.set(cam.GetPosition()); - 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) { - // VoxelWorldManager.GenerateChunks(ChunkPos, new Vector3i(5, 5, 5)); - // VoxelWorldManager.UnloadFarChunks(ChunkPos, 10); - //} else { - //} - - for (int i = 0; i < VisualisedCollisionActor3D.CollisionVisuals.size(); i++) { - VisualisedCollisionActor3D.CollisionVisuals.get(i).Update(); - } for(int i = 0; i < Actor3DElement.ElementNames.size(); i++){ if( Actor3DElement.ActorElementRegistry.get(Actor3DElement.ElementNames.get(i)) == null) continue; Actor3DElement.ActorElementRegistry.get(Actor3DElement.ElementNames.get(i)).UpdateModelMatrix(); @@ -688,9 +678,16 @@ public class GameCore implements GameLogic { float DeltaTime = (float)FrameDiffNanoSeconds/(PhysicsFrameTime*1000000f); Camera cam = engineInstance.scene().GetCamera(); Project3D projection = engineInstance.scene().GetProjection(); + 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)); - VoxelWorldManager.UnloadFarChunks(ChunkPos, 12,cam.GetViewMatrix(),projection.GetProjectionMatrix()); - VoxelWorldManager.GenerateChunks(ChunkPos, new Vector3i(12,6,12),cam.GetViewMatrix(),projection.GetProjectionMatrix()); + 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, 20,cam.GetViewMatrix(),projection.GetProjectionMatrix()); + VoxelWorldManager.GenerateChunks(ChunkPos, new Vector3i(20,8,20),cam.GetViewMatrix(),projection.GetProjectionMatrix()); + } else { + VoxelWorldManager.UnloadFarChunks(ChunkPos, 64,cam.GetViewMatrix(),projection.GetProjectionMatrix()); + VoxelWorldManager.GenerateChunks(ChunkPos, new Vector3i(32,12,32),cam.GetViewMatrix(),projection.GetProjectionMatrix()); + } + LastCamRotation.set(CamRot); if(PrimaryRuntime.IsServer){ /* if(UseLegacyNetworking) Server.LegacyCollectIncomingPackets(); else*/ //Server.CollectIncomingPackets(); 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 a7d0562..ca06519 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 @@ -70,7 +70,7 @@ public class VoxelWorldManager { private static Vector3f min = new Vector3f(); private static Vector3f min2 = new Vector3f(); - public static void GenerateChunks(Vector3i Position, Vector3i Radius, Matrix4f cameraView,Matrix4f projectionMatrix) { + public static synchronized void GenerateChunks(Vector3i Position, Vector3i Radius, Matrix4f cameraView,Matrix4f projectionMatrix) { projectionMatrix.mul(cameraView, viewProjectionMatrix); frustumIntersection.set(viewProjectionMatrix); @@ -190,25 +190,28 @@ public class VoxelWorldManager { } - public static void UnloadFarChunks(Vector3i centerChunk, int unloadRadius,Matrix4f cameraView,Matrix4f projectionMatrix) { + public static synchronized void UnloadFarChunks(Vector3i centerChunk, int unloadRadius,Matrix4f cameraView,Matrix4f projectionMatrix) { int maxDistSq = unloadRadius * unloadRadius; - + projectionMatrix.mul(cameraView, viewProjectionMatrix); + frustumIntersection.set(viewProjectionMatrix); RenderChunks.entrySet().removeIf(entry -> { Vector3i pos = entry.getKey(); - - projectionMatrix.mul(cameraView, viewProjectionMatrix); - frustumIntersection.set(viewProjectionMatrix); min.set(pos.x * CHUNK_SIZE, pos.y * CHUNK_SIZE, pos.z * CHUNK_SIZE); max.set(min.x + CHUNK_SIZE, min.y + CHUNK_SIZE, min.z + CHUNK_SIZE); - + boolean InView = frustumIntersection.testAab(min.x, min.y, min.z, max.x, max.y, max.z); + if (!InView) { + 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; - boolean InView = frustumIntersection.testAab(min.x, min.y, min.z, max.x, max.y, max.z); - if (distSq > maxDistSq || !InView) { + if (distSq > maxDistSq) { RenderChunk chunk = entry.getValue(); Resources.meshPool().free(chunk); diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/RenderPasses/Lighting/LightRenderer.java b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/RenderPasses/Lighting/LightRenderer.java index f55ed77..8470029 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/RenderPasses/Lighting/LightRenderer.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/RenderPasses/Lighting/LightRenderer.java @@ -201,12 +201,10 @@ public class LightRenderer { private static ShaderModule[] CreateShaderModules(VulkanContext VkCtx, LightSpecConsts lightSpecConsts, boolean shadowPipeline) { if (EngineConfig.getInstance().RecompileShaders()) { ShaderCompiler.CompileGLSLShaderOnChange(VERTEX_SHADER_FILE_GLSL, Shaderc.shaderc_glsl_vertex_shader); - //ShaderCompiler.CompileGLSLShaderOnChange( FRAGMENT_SHADER_FILE_GLSL, Shaderc.shaderc_glsl_fragment_shader); ShaderCompiler.CompileGLSLShaderOnChange(shadowPipeline ? FRAGMENT_SHADER_FILE_GLSL : NO_SHADOWS_FRAGMENT_SHADER_FILE_GLSL, Shaderc.shaderc_glsl_fragment_shader); } return new ShaderModule[]{ new ShaderModule(VkCtx, VK_SHADER_STAGE_VERTEX_BIT, VERTEX_SHADER_FILE_SPV, null), - //new ShaderModule(VkCtx, VK_SHADER_STAGE_FRAGMENT_BIT, FRAGMENT_SHADER_FILE_SPV, lightSpecConsts.getSpecInfo()), new ShaderModule(VkCtx, VK_SHADER_STAGE_FRAGMENT_BIT, shadowPipeline ? FRAGMENT_SHADER_FILE_SPV : NO_SHADOWS_FRAGMENT_SHADER_FILE_SPV, shadowPipeline ? lightSpecConsts.getSpecInfo() : null), }; }