diff --git a/Content/Editor/MaterialTemplates/Terrain.shader b/Content/Editor/MaterialTemplates/Terrain.shader index b60ca2a3c..32395d583 100644 --- a/Content/Editor/MaterialTemplates/Terrain.shader +++ b/Content/Editor/MaterialTemplates/Terrain.shader @@ -269,24 +269,16 @@ float CalcLOD(float2 xy, float4 morph) if ((xy.x + xy.y) > 1) { if (xy.x < xy.y) - { lod = lodCalculated.w; - } else - { lod = lodCalculated.z; - } } else { if (xy.x < xy.y) - { lod = lodCalculated.y; - } else - { lod = lodCalculated.x; - } } return lod; diff --git a/Source/Editor/Tools/Terrain/CreateTerrainDialog.cs b/Source/Editor/Tools/Terrain/CreateTerrainDialog.cs index 537121001..252891d44 100644 --- a/Source/Editor/Tools/Terrain/CreateTerrainDialog.cs +++ b/Source/Editor/Tools/Terrain/CreateTerrainDialog.cs @@ -26,7 +26,9 @@ namespace FlaxEditor.Tools.Terrain _31 = 31, _63 = 63, _127 = 127, + _254 = 254, _255 = 255, + _511 = 511, } private class Options @@ -34,7 +36,7 @@ namespace FlaxEditor.Tools.Terrain [EditorOrder(100), EditorDisplay("Layout", "Number Of Patches"), DefaultValue(typeof(Int2), "1,1"), Limit(0, 512), Tooltip("Amount of terrain patches in each direction (X and Z). Each terrain patch contains a grid of 16 chunks. Patches can be later added or removed from terrain using a terrain editor tool.")] public Int2 NumberOfPatches = new Int2(1, 1); - [EditorOrder(110), EditorDisplay("Layout"), DefaultValue(ChunkSizes._127), Tooltip("The size of the chunk (amount of quads per edge for the highest LOD). Must be power of two minus one (eg. 63).")] + [EditorOrder(110), EditorDisplay("Layout"), DefaultValue(ChunkSizes._127), Tooltip("The size of the chunk (amount of quads per edge for the highest LOD).")] public ChunkSizes ChunkSize = ChunkSizes._127; [EditorOrder(120), EditorDisplay("Layout", "LOD Count"), DefaultValue(6), Limit(1, FlaxEngine.Terrain.MaxLODs), Tooltip("The maximum Level Of Details count. The actual amount of LODs may be lower due to provided chunk size (each LOD has 4 times less quads).")] diff --git a/Source/Engine/Terrain/TerrainManager.cpp b/Source/Engine/Terrain/TerrainManager.cpp index 0980bcc7a..df9b6d706 100644 --- a/Source/Engine/Terrain/TerrainManager.cpp +++ b/Source/Engine/Terrain/TerrainManager.cpp @@ -98,10 +98,12 @@ bool TerrainManager::GetChunkGeometry(DrawCall& drawCall, int32 chunkSize, int32 // Prepare const int32 vertexCount = (chunkSize + 1) >> lodIndex; chunkSize = vertexCount - 1; + const bool indexUse16bits = chunkSize * chunkSize * vertexCount < MAX_uint16; + const int32 indexSize = indexUse16bits ? sizeof(uint16) : sizeof(uint32); const int32 indexCount = chunkSize * chunkSize * 2 * 3; const int32 vertexCount2 = vertexCount * vertexCount; const int32 vbSize = sizeof(TerrainVertex) * vertexCount2; - const int32 ibSize = sizeof(uint16) * indexCount; + const int32 ibSize = indexSize * indexCount; TempData.Clear(); TempData.EnsureCapacity(Math::Max(vbSize, ibSize)); @@ -140,26 +142,51 @@ bool TerrainManager::GetChunkGeometry(DrawCall& drawCall, int32 chunkSize, int32 // Create index buffer auto ib = GPUDevice::Instance->CreateBuffer(TEXT("TerrainChunk.IB")); - auto index = (uint16*)TempData.Get(); - for (int32 z = 0; z < chunkSize; z++) + if (indexUse16bits) { - for (int32 x = 0; x < chunkSize; x++) + auto index = (uint16*)TempData.Get(); + for (int32 z = 0; z < chunkSize; z++) { - const uint16 i00 = (x + 0) + (z + 0) * vertexCount; - const uint16 i10 = (x + 1) + (z + 0) * vertexCount; - const uint16 i11 = (x + 1) + (z + 1) * vertexCount; - const uint16 i01 = (x + 0) + (z + 1) * vertexCount; + for (int32 x = 0; x < chunkSize; x++) + { + const uint16 i00 = (x + 0) + (z + 0) * vertexCount; + const uint16 i10 = (x + 1) + (z + 0) * vertexCount; + const uint16 i11 = (x + 1) + (z + 1) * vertexCount; + const uint16 i01 = (x + 0) + (z + 1) * vertexCount; - *index++ = i00; - *index++ = i11; - *index++ = i10; + *index++ = i00; + *index++ = i11; + *index++ = i10; - *index++ = i00; - *index++ = i01; - *index++ = i11; + *index++ = i00; + *index++ = i01; + *index++ = i11; + } } } - desc = GPUBufferDescription::Index(sizeof(uint16), indexCount, TempData.Get()); + else + { + auto index = (uint32*)TempData.Get(); + for (int32 z = 0; z < chunkSize; z++) + { + for (int32 x = 0; x < chunkSize; x++) + { + const uint32 i00 = (x + 0) + (z + 0) * vertexCount; + const uint32 i10 = (x + 1) + (z + 0) * vertexCount; + const uint32 i11 = (x + 1) + (z + 1) * vertexCount; + const uint32 i01 = (x + 0) + (z + 1) * vertexCount; + + *index++ = i00; + *index++ = i11; + *index++ = i10; + + *index++ = i00; + *index++ = i01; + *index++ = i11; + } + } + } + desc = GPUBufferDescription::Index(indexSize, indexCount, TempData.Get()); if (ib->Init(desc)) { vb->ReleaseGPU();