| 83 | } |
| 84 | |
| 85 | void TerrainChunk::Draw(const RenderContext& renderContext) const |
| 86 | { |
| 87 | const int32 lod = _cachedDrawLOD; |
| 88 | const int32 minLod = Math::Max(lod + 1, 0); |
| 89 | const int32 chunkSize = _patch->_terrain->GetChunkSize(); |
| 90 | |
| 91 | // Setup draw call |
| 92 | DrawCall drawCall; |
| 93 | if (TerrainManager::GetChunkGeometry(drawCall, chunkSize, lod)) |
| 94 | return; |
| 95 | if (!_neighbors[0]) |
| 96 | const_cast<TerrainChunk*>(this)->CacheNeighbors(); |
| 97 | drawCall.InstanceCount = 1; |
| 98 | drawCall.Material = _cachedDrawMaterial; |
| 99 | renderContext.View.GetWorldMatrix(_transform, drawCall.World); |
| 100 | drawCall.ObjectPosition = drawCall.World.GetTranslation(); |
| 101 | drawCall.ObjectRadius = (float)_sphere.Radius; |
| 102 | drawCall.Terrain.Patch = _patch; |
| 103 | drawCall.Terrain.HeightmapUVScaleBias = _heightmapUVScaleBias; |
| 104 | drawCall.Terrain.OffsetUV = Vector2((float)(_patch->_x * Terrain::ChunksCountEdge + _x), (float)(_patch->_z * Terrain::ChunksCountEdge + _z)); |
| 105 | drawCall.Terrain.CurrentLOD = (float)lod; |
| 106 | drawCall.Terrain.ChunkSizeNextLOD = (float)(((chunkSize + 1) >> (lod + 1)) - 1); |
| 107 | drawCall.Terrain.TerrainChunkSizeLOD0 = TERRAIN_UNITS_PER_VERTEX * chunkSize; |
| 108 | // TODO: try using SIMD clamping for 4 chunks at once |
| 109 | drawCall.Terrain.NeighborLOD.X = (float)Math::Clamp<int32>(_neighbors[0]->_cachedDrawLOD, lod, minLod); |
| 110 | drawCall.Terrain.NeighborLOD.Y = (float)Math::Clamp<int32>(_neighbors[1]->_cachedDrawLOD, lod, minLod); |
| 111 | drawCall.Terrain.NeighborLOD.Z = (float)Math::Clamp<int32>(_neighbors[2]->_cachedDrawLOD, lod, minLod); |
| 112 | drawCall.Terrain.NeighborLOD.W = (float)Math::Clamp<int32>(_neighbors[3]->_cachedDrawLOD, lod, minLod); |
| 113 | const auto scene = _patch->_terrain->GetScene(); |
| 114 | const auto flags = _patch->_terrain->_staticFlags; |
| 115 | if ((flags & StaticFlags::Lightmap) != StaticFlags::None && scene) |
| 116 | { |
| 117 | drawCall.Terrain.Lightmap = scene->LightmapsData.GetReadyLightmap(Lightmap.TextureIndex); |
| 118 | drawCall.Terrain.LightmapUVsArea = Lightmap.UVsArea; |
| 119 | } |
| 120 | else |
| 121 | { |
| 122 | drawCall.Terrain.Lightmap = nullptr; |
| 123 | drawCall.Terrain.LightmapUVsArea = Rectangle::Empty; |
| 124 | } |
| 125 | drawCall.PerInstanceRandom = _perInstanceRandom; |
| 126 | drawCall.SetStencilValue(_patch->_terrain->GetLayer()); |
| 127 | #if USE_EDITOR |
| 128 | if (renderContext.View.Mode == ViewMode::LightmapUVsDensity) |
| 129 | drawCall.Surface.LODDitherFactor = 1.0f; // See LightmapUVsDensityMaterialShader |
| 130 | #endif |
| 131 | |
| 132 | // Add half-texel offset for heightmap sampling in vertex shader |
| 133 | //const float lodHeightmapSize = Math::Max(1, drawCall.TerrainData.Heightmap->Width() >> lod); |
| 134 | //const float halfTexelOffset = 0.5f / lodHeightmapSize; |
| 135 | //drawCall.TerrainData.HeightmapUVScaleBias.Z += halfTexelOffset; |
| 136 | //drawCall.TerrainData.HeightmapUVScaleBias.W += halfTexelOffset; |
| 137 | |
| 138 | // Submit draw call |
| 139 | const DrawPass drawModes = _patch->_terrain->DrawModes & renderContext.View.Pass & drawCall.Material->GetDrawModes(); |
| 140 | if (drawModes != DrawPass::None) |
| 141 | renderContext.List->AddDrawCall(renderContext, drawModes, flags, drawCall, true); |
| 142 | } |
nothing calls this directly
no test coverage detected