| 81 | } |
| 82 | |
| 83 | bool TerrainManager::GetChunkGeometry(DrawCall& drawCall, int32 chunkSize, int32 lodIndex) |
| 84 | { |
| 85 | const int32 chunkSizeLOD0 = chunkSize; |
| 86 | |
| 87 | // Try fast lookup |
| 88 | GeometryData* data; |
| 89 | const uint32 key = (uint32)chunkSizeLOD0 | ((uint32)lodIndex << 20); |
| 90 | if (Lookup.TryGet(key, data)) |
| 91 | { |
| 92 | data->GetChunkGeometry(drawCall); |
| 93 | return false; |
| 94 | } |
| 95 | |
| 96 | ASSERT(chunkSize >= 3 && chunkSize < MAX_uint16); |
| 97 | ASSERT(lodIndex >= 0 && lodIndex <= TERRAIN_MAX_LODS); |
| 98 | |
| 99 | ScopeLock lock(GeometryLocker); |
| 100 | |
| 101 | // Check if someone just created buffer |
| 102 | if (Lookup.TryGet(key, data)) |
| 103 | { |
| 104 | data->GetChunkGeometry(drawCall); |
| 105 | return false; |
| 106 | } |
| 107 | PROFILE_MEM(LevelTerrain); |
| 108 | |
| 109 | // Prepare |
| 110 | const int32 vertexCount = (chunkSize + 1) >> lodIndex; |
| 111 | chunkSize = vertexCount - 1; |
| 112 | const bool indexUse16bits = chunkSize * chunkSize * vertexCount < MAX_uint16; |
| 113 | const int32 indexSize = indexUse16bits ? sizeof(uint16) : sizeof(uint32); |
| 114 | const int32 indexCount = chunkSize * chunkSize * 2 * 3; |
| 115 | const int32 vertexCount2 = vertexCount * vertexCount; |
| 116 | const int32 vbSize = sizeof(TerrainVertex) * vertexCount2; |
| 117 | const int32 ibSize = indexSize * indexCount; |
| 118 | TempData.Clear(); |
| 119 | TempData.EnsureCapacity(Math::Max(vbSize, ibSize)); |
| 120 | |
| 121 | // Create vertex buffer |
| 122 | auto vb = GPUDevice::Instance->CreateBuffer(TEXT("TerrainChunk.VB")); |
| 123 | auto vertex = (TerrainVertex*)TempData.Get(); |
| 124 | const float vertexTexelSnapTexCoord = 1.0f / chunkSize; |
| 125 | for (int32 z = 0; z < vertexCount; z++) |
| 126 | { |
| 127 | for (int32 x = 0; x < vertexCount; x++) |
| 128 | { |
| 129 | vertex->TexCoord.X = x * vertexTexelSnapTexCoord; |
| 130 | vertex->TexCoord.Y = z * vertexTexelSnapTexCoord; |
| 131 | |
| 132 | // Smooth LODs morphing based on Barycentric coordinates to morph to the lower LOD near chunk edges |
| 133 | Float4 coord(vertex->TexCoord.Y, vertex->TexCoord.X, 1.0f - vertex->TexCoord.X, 1.0f - vertex->TexCoord.Y); |
| 134 | |
| 135 | // Apply some contrast |
| 136 | const float AdjustPower = 0.3f; |
| 137 | coord.X = Math::Pow(coord.X, AdjustPower); |
| 138 | coord.Y = Math::Pow(coord.Y, AdjustPower); |
| 139 | coord.Z = Math::Pow(coord.Z, AdjustPower); |
| 140 | coord.W = Math::Pow(coord.W, AdjustPower); |
nothing calls this directly
no test coverage detected