Various fixes and improvements for large worlds rendering
This commit is contained in:
BIN
Content/Shaders/GlobalSignDistanceField.flax
(Stored with Git LFS)
BIN
Content/Shaders/GlobalSignDistanceField.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Shaders/Sky.flax
(Stored with Git LFS)
BIN
Content/Shaders/Sky.flax
(Stored with Git LFS)
Binary file not shown.
@@ -19,6 +19,8 @@
|
||||
|
||||
PACK_STRUCT(struct Data {
|
||||
Matrix WVP;
|
||||
Float3 ViewOffset;
|
||||
float Padding;
|
||||
GBufferData GBuffer;
|
||||
AtmosphericFogData Fog;
|
||||
});
|
||||
@@ -178,6 +180,7 @@ void Sky::DrawFog(GPUContext* context, RenderContext& renderContext, GPUTextureV
|
||||
// Setup constants data
|
||||
Data data;
|
||||
GBufferPass::SetInputs(renderContext.View, data.GBuffer);
|
||||
data.ViewOffset = renderContext.View.Origin + GetPosition();
|
||||
InitConfig(data.Fog);
|
||||
data.Fog.AtmosphericFogSunPower *= SunLight ? SunLight->Brightness : 1.0f;
|
||||
bool useSpecularLight = (renderContext.View.Flags & ViewFlags::SpecularLight) != 0;
|
||||
@@ -216,6 +219,7 @@ void Sky::ApplySky(GPUContext* context, RenderContext& renderContext, const Matr
|
||||
Matrix::Multiply(world, renderContext.View.Frustum.GetMatrix(), m);
|
||||
Matrix::Transpose(m, data.WVP);
|
||||
GBufferPass::SetInputs(renderContext.View, data.GBuffer);
|
||||
data.ViewOffset = renderContext.View.Origin + GetPosition();
|
||||
InitConfig(data.Fog);
|
||||
//data.Fog.AtmosphericFogSunPower *= SunLight ? SunLight->Brightness : 1.0f;
|
||||
bool useSpecularLight = (renderContext.View.Flags & ViewFlags::SpecularLight) != 0;
|
||||
|
||||
@@ -37,6 +37,15 @@ float SkyLight::GetScaledRadius() const
|
||||
return _radius * _transform.Scale.MaxValue();
|
||||
}
|
||||
|
||||
CubeTexture* SkyLight::GetSource() const
|
||||
{
|
||||
if (Mode == Modes::CaptureScene)
|
||||
return _bakedProbe;
|
||||
if (Mode == Modes::CustomTexture)
|
||||
return CustomTexture.Get();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void SkyLight::Bake(float timeout)
|
||||
{
|
||||
#if COMPILE_WITH_PROBES_BAKING
|
||||
|
||||
@@ -63,7 +63,6 @@ public:
|
||||
/// <summary>
|
||||
/// Gets the radius.
|
||||
/// </summary>
|
||||
/// <returns>The value.</returns>
|
||||
API_PROPERTY(Attributes="EditorOrder(29), DefaultValue(1000000.0f), Limit(0), EditorDisplay(\"Light\")")
|
||||
FORCE_INLINE float GetRadius() const
|
||||
{
|
||||
@@ -73,8 +72,7 @@ public:
|
||||
/// <summary>
|
||||
/// Sets the radius.
|
||||
/// </summary>
|
||||
/// <param name="value">The value.</param>
|
||||
void SetRadius(float value);
|
||||
API_PROPERTY() void SetRadius(float value);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the scaled radius of the sky light.
|
||||
@@ -84,15 +82,7 @@ public:
|
||||
/// <summary>
|
||||
/// Gets the light source texture.
|
||||
/// </summary>
|
||||
/// <returns>The cube texture.</returns>
|
||||
CubeTexture* GetSource() const
|
||||
{
|
||||
if (Mode == Modes::CaptureScene)
|
||||
return _bakedProbe;
|
||||
if (Mode == Modes::CustomTexture)
|
||||
return CustomTexture.Get();
|
||||
return nullptr;
|
||||
}
|
||||
CubeTexture* GetSource() const;
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
|
||||
@@ -232,20 +232,18 @@ void StaticModel::Draw(RenderContext& renderContext)
|
||||
const DrawPass drawModes = (DrawPass)(DrawModes & renderContext.View.Pass);
|
||||
if (!Model || !Model->IsLoaded() || !Model->CanBeRendered() || drawModes == DrawPass::None)
|
||||
return;
|
||||
|
||||
Matrix world;
|
||||
renderContext.View.GetWorldMatrix(_transform, world);
|
||||
|
||||
if (renderContext.View.Pass == DrawPass::GlobalSDF)
|
||||
{
|
||||
GlobalSignDistanceFieldPass::Instance()->RasterizeModelSDF(this, Model->SDF, world, _box);
|
||||
GlobalSignDistanceFieldPass::Instance()->RasterizeModelSDF(this, Model->SDF, _transform, _box);
|
||||
return;
|
||||
}
|
||||
if (renderContext.View.Pass == DrawPass::GlobalSurfaceAtlas)
|
||||
{
|
||||
GlobalSurfaceAtlasPass::Instance()->RasterizeActor(this, this, _sphere, world, Model->LODs.Last().GetBox());
|
||||
GlobalSurfaceAtlasPass::Instance()->RasterizeActor(this, this, _sphere, _transform, Model->LODs.Last().GetBox());
|
||||
return;
|
||||
}
|
||||
Matrix world;
|
||||
renderContext.View.GetWorldMatrix(_transform, world);
|
||||
GEOMETRY_DRAW_STATE_EVENT_BEGIN(_drawState, world);
|
||||
|
||||
// Flush vertex colors if need to
|
||||
|
||||
@@ -1282,8 +1282,7 @@ void GlobalSurfaceAtlasPass::RasterizeActor(Actor* actor, void* actorObject, con
|
||||
// Calculate object bounds size in the view
|
||||
OrientedBoundingBox viewBounds(object->Bounds);
|
||||
viewBounds.Transform(tile->ViewMatrix);
|
||||
Float3 viewExtent;
|
||||
viewExtent = viewBounds.Transformation.LocalToWorldVector(viewBounds.Extents);
|
||||
Float3 viewExtent = viewBounds.Transformation.LocalToWorldVector(viewBounds.Extents);
|
||||
tile->ViewBoundsSize = viewExtent.GetAbsolute() * 2.0f;
|
||||
|
||||
// Per-tile data
|
||||
|
||||
@@ -80,7 +80,7 @@ public:
|
||||
void RenderDebug(RenderContext& renderContext, GPUContext* context, GPUTexture* output);
|
||||
|
||||
// Rasterize actor into the Global Surface Atlas. Call it from actor Draw() method during DrawPass::GlobalSurfaceAtlas.
|
||||
void RasterizeActor(Actor* actor, void* actorObject, const BoundingSphere& actorObjectBounds, const Matrix& localToWorld, const BoundingBox& localBounds, uint32 tilesMask = MAX_uint32, bool useVisibility = true);
|
||||
void RasterizeActor(Actor* actor, void* actorObject, const BoundingSphere& actorObjectBounds, const Transform& localToWorld, const BoundingBox& localBounds, uint32 tilesMask = MAX_uint32, bool useVisibility = true);
|
||||
|
||||
private:
|
||||
#if COMPILE_WITH_DEV_ENV
|
||||
|
||||
@@ -173,6 +173,7 @@ public:
|
||||
int32 Resolution = 0;
|
||||
GPUTexture* Texture = nullptr;
|
||||
GPUTexture* TextureMip = nullptr;
|
||||
Vector3 Origin = Vector3::Zero;
|
||||
Array<CascadeData, FixedAllocation<4>> Cascades;
|
||||
HashSet<ScriptingTypeHandle> ObjectTypes;
|
||||
HashSet<GPUTexture*> SDFTextures;
|
||||
@@ -431,7 +432,6 @@ bool GlobalSignDistanceFieldPass::Render(RenderContext& renderContext, GPUContex
|
||||
}
|
||||
desc.Width = resolutionMip * cascadesCount;
|
||||
desc.Height = desc.Depth = resolutionMip;
|
||||
for (auto& cascade : sdfData.Cascades)
|
||||
{
|
||||
GPUTexture*& texture = sdfData.TextureMip;
|
||||
if (texture && texture->Width() != desc.Width)
|
||||
@@ -446,6 +446,13 @@ bool GlobalSignDistanceFieldPass::Render(RenderContext& renderContext, GPUContex
|
||||
return true;
|
||||
}
|
||||
}
|
||||
uint64 memoryUsage = sdfData.Texture->GetMemoryUsage() + sdfData.TextureMip->GetMemoryUsage();
|
||||
LOG(Info, "Global SDF memory usage: {0} MB", memoryUsage / 1024 / 1024);
|
||||
}
|
||||
if (sdfData.Origin != renderContext.View.Origin)
|
||||
{
|
||||
sdfData.Origin = renderContext.View.Origin;
|
||||
updated = true;
|
||||
}
|
||||
GPUTexture* tmpMip = nullptr;
|
||||
if (updated)
|
||||
@@ -456,23 +463,20 @@ bool GlobalSignDistanceFieldPass::Render(RenderContext& renderContext, GPUContex
|
||||
cascade.NonEmptyChunks.Clear();
|
||||
cascade.StaticChunks.Clear();
|
||||
}
|
||||
uint64 memoryUsage = sdfData.Texture->GetMemoryUsage();
|
||||
context->ClearUA(sdfData.Texture, Float4::One);
|
||||
memoryUsage += sdfData.TextureMip->GetMemoryUsage();
|
||||
context->ClearUA(sdfData.TextureMip, Float4::One);
|
||||
LOG(Info, "Global SDF memory usage: {0} MB", memoryUsage / 1024 / 1024);
|
||||
}
|
||||
for (SceneRendering* scene : renderContext.List->Scenes)
|
||||
sdfData.ListenSceneRendering(scene);
|
||||
|
||||
// Calculate origin for Global SDF by shifting it towards the view direction to account for better view frustum coverage
|
||||
Float3 viewOrigin = renderContext.View.Position;
|
||||
Float3 viewPosition = renderContext.View.Position;
|
||||
{
|
||||
Float3 viewDirection = renderContext.View.Direction;
|
||||
const float cascade0Distance = distanceExtent * cascadesDistanceScales[0];
|
||||
const Vector2 viewRayHit = CollisionsHelper::LineHitsBox(viewOrigin, viewOrigin + viewDirection * (cascade0Distance * 2.0f), viewOrigin - cascade0Distance, viewOrigin + cascade0Distance);
|
||||
const Vector2 viewRayHit = CollisionsHelper::LineHitsBox(viewPosition, viewPosition + viewDirection * (cascade0Distance * 2.0f), viewPosition - cascade0Distance, viewPosition + cascade0Distance);
|
||||
const float viewOriginOffset = (float)viewRayHit.Y * cascade0Distance * 0.6f;
|
||||
viewOrigin += viewDirection * viewOriginOffset;
|
||||
viewPosition += viewDirection * viewOriginOffset;
|
||||
}
|
||||
|
||||
// Rasterize world geometry into Global SDF
|
||||
@@ -499,7 +503,7 @@ bool GlobalSignDistanceFieldPass::Render(RenderContext& renderContext, GPUContex
|
||||
const float cascadeVoxelSize = cascadeMaxDistance / (float)resolution;
|
||||
const float cascadeChunkSize = cascadeVoxelSize * GLOBAL_SDF_RASTERIZE_CHUNK_SIZE;
|
||||
static_assert(GLOBAL_SDF_RASTERIZE_CHUNK_SIZE % GLOBAL_SDF_RASTERIZE_MIP_FACTOR == 0, "Adjust chunk size to match the mip factor scale.");
|
||||
const Float3 center = Float3::Floor(viewOrigin / cascadeChunkSize) * cascadeChunkSize;
|
||||
const Float3 center = Float3::Floor(viewPosition / cascadeChunkSize) * cascadeChunkSize;
|
||||
//const Float3 center = Float3::Zero;
|
||||
BoundingBox cascadeBounds(center - cascadeDistance, center + cascadeDistance);
|
||||
// TODO: add scene detail scale factor to PostFx settings (eg. to increase or decrease scene details and quality)
|
||||
@@ -533,11 +537,14 @@ bool GlobalSignDistanceFieldPass::Render(RenderContext& renderContext, GPUContex
|
||||
_sdfData = &sdfData;
|
||||
{
|
||||
PROFILE_CPU_NAMED("Draw");
|
||||
BoundingBox cascadeBoundsWorld = cascadeBounds;
|
||||
cascadeBoundsWorld.Minimum += sdfData.Origin;
|
||||
cascadeBoundsWorld.Maximum += sdfData.Origin;
|
||||
for (SceneRendering* scene : renderContext.List->Scenes)
|
||||
{
|
||||
for (const auto& e : scene->Actors)
|
||||
{
|
||||
if (viewMask & e.LayerMask && e.Bounds.Radius >= minObjectRadius && CollisionsHelper::BoxIntersectsSphere(cascadeBounds, e.Bounds))
|
||||
if (viewMask & e.LayerMask && e.Bounds.Radius >= minObjectRadius && CollisionsHelper::BoxIntersectsSphere(cascadeBoundsWorld, e.Bounds))
|
||||
{
|
||||
e.Actor->Draw(renderContext);
|
||||
}
|
||||
@@ -578,7 +585,6 @@ bool GlobalSignDistanceFieldPass::Render(RenderContext& renderContext, GPUContex
|
||||
// TODO: don't stall with UAV barrier on D3D12/Vulkan if UAVs don't change between dispatches
|
||||
}
|
||||
}
|
||||
// TODO: rasterize models into global sdf relative to the cascade origin to prevent fp issues on large worlds
|
||||
{
|
||||
PROFILE_GPU_CPU("Rasterize Chunks");
|
||||
|
||||
@@ -838,7 +844,7 @@ void GlobalSignDistanceFieldPass::RenderDebug(RenderContext& renderContext, GPUC
|
||||
context->DrawFullscreenTriangle();
|
||||
}
|
||||
|
||||
void GlobalSignDistanceFieldPass::RasterizeModelSDF(Actor* actor, const ModelBase::SDFData& sdf, const Matrix& localToWorld, const BoundingBox& objectBounds)
|
||||
void GlobalSignDistanceFieldPass::RasterizeModelSDF(Actor* actor, const ModelBase::SDFData& sdf, const Transform& localToWorld, const BoundingBox& objectBounds)
|
||||
{
|
||||
if (!sdf.Texture || sdf.Texture->ResidentMipLevels() == 0)
|
||||
return;
|
||||
@@ -846,15 +852,16 @@ void GlobalSignDistanceFieldPass::RasterizeModelSDF(Actor* actor, const ModelBas
|
||||
// Setup object data
|
||||
BoundingBox objectBoundsCascade;
|
||||
const float objectMargin = _voxelSize * GLOBAL_SDF_RASTERIZE_CHUNK_MARGIN;
|
||||
Vector3::Clamp(objectBounds.Minimum - objectMargin, _cascadeBounds.Minimum, _cascadeBounds.Maximum, objectBoundsCascade.Minimum);
|
||||
Vector3::Clamp(objectBounds.Minimum - _sdfData->Origin - objectMargin, _cascadeBounds.Minimum, _cascadeBounds.Maximum, objectBoundsCascade.Minimum);
|
||||
Vector3::Subtract(objectBoundsCascade.Minimum, _cascadeBounds.Minimum, objectBoundsCascade.Minimum);
|
||||
Vector3::Clamp(objectBounds.Maximum + objectMargin, _cascadeBounds.Minimum, _cascadeBounds.Maximum, objectBoundsCascade.Maximum);
|
||||
Vector3::Clamp(objectBounds.Maximum - _sdfData->Origin + objectMargin, _cascadeBounds.Minimum, _cascadeBounds.Maximum, objectBoundsCascade.Maximum);
|
||||
Vector3::Subtract(objectBoundsCascade.Maximum, _cascadeBounds.Minimum, objectBoundsCascade.Maximum);
|
||||
const float chunkSize = _voxelSize * GLOBAL_SDF_RASTERIZE_CHUNK_SIZE;
|
||||
Int3 objectChunkMin(objectBoundsCascade.Minimum / chunkSize);
|
||||
Int3 objectChunkMax(objectBoundsCascade.Maximum / chunkSize);
|
||||
Matrix worldToLocal, volumeToWorld;
|
||||
Matrix::Invert(localToWorld, worldToLocal);
|
||||
Matrix localToWorldM, worldToLocal, volumeToWorld;
|
||||
Matrix::Transformation(localToWorld.Scale, localToWorld.Orientation, localToWorld.Translation - _sdfData->Origin, localToWorldM);
|
||||
Matrix::Invert(localToWorldM, worldToLocal);
|
||||
BoundingBox localVolumeBounds(sdf.LocalBoundsMin, sdf.LocalBoundsMax);
|
||||
Float3 volumeLocalBoundsExtent = localVolumeBounds.GetSize() * 0.5f;
|
||||
Matrix worldToVolume = worldToLocal * Matrix::Translation(-(localVolumeBounds.Minimum + volumeLocalBoundsExtent));
|
||||
@@ -862,7 +869,7 @@ void GlobalSignDistanceFieldPass::RasterizeModelSDF(Actor* actor, const ModelBas
|
||||
|
||||
// Pick the SDF mip for the cascade
|
||||
int32 mipLevelIndex = 1;
|
||||
float worldUnitsPerVoxel = sdf.WorldUnitsPerVoxel * localToWorld.GetScaleVector().MaxValue() * 2;
|
||||
float worldUnitsPerVoxel = sdf.WorldUnitsPerVoxel * localToWorld.Scale.MaxValue() * 2;
|
||||
while (_voxelSize > worldUnitsPerVoxel && mipLevelIndex < sdf.Texture->MipLevels())
|
||||
{
|
||||
mipLevelIndex++;
|
||||
@@ -925,7 +932,7 @@ void GlobalSignDistanceFieldPass::RasterizeModelSDF(Actor* actor, const ModelBas
|
||||
}
|
||||
}
|
||||
|
||||
void GlobalSignDistanceFieldPass::RasterizeHeightfield(Actor* actor, GPUTexture* heightfield, const Matrix& localToWorld, const BoundingBox& objectBounds, const Float4& localToUV)
|
||||
void GlobalSignDistanceFieldPass::RasterizeHeightfield(Actor* actor, GPUTexture* heightfield, const Transform& localToWorld, const BoundingBox& objectBounds, const Float4& localToUV)
|
||||
{
|
||||
if (!heightfield || heightfield->ResidentMipLevels() == 0)
|
||||
return;
|
||||
@@ -933,9 +940,9 @@ void GlobalSignDistanceFieldPass::RasterizeHeightfield(Actor* actor, GPUTexture*
|
||||
// Setup object data
|
||||
BoundingBox objectBoundsCascade;
|
||||
const float objectMargin = _voxelSize * GLOBAL_SDF_RASTERIZE_CHUNK_MARGIN;
|
||||
Vector3::Clamp(objectBounds.Minimum - objectMargin, _cascadeBounds.Minimum, _cascadeBounds.Maximum, objectBoundsCascade.Minimum);
|
||||
Vector3::Clamp(objectBounds.Minimum - _sdfData->Origin - objectMargin, _cascadeBounds.Minimum, _cascadeBounds.Maximum, objectBoundsCascade.Minimum);
|
||||
Vector3::Subtract(objectBoundsCascade.Minimum, _cascadeBounds.Minimum, objectBoundsCascade.Minimum);
|
||||
Vector3::Clamp(objectBounds.Maximum + objectMargin, _cascadeBounds.Minimum, _cascadeBounds.Maximum, objectBoundsCascade.Maximum);
|
||||
Vector3::Clamp(objectBounds.Maximum - _sdfData->Origin + objectMargin, _cascadeBounds.Minimum, _cascadeBounds.Maximum, objectBoundsCascade.Maximum);
|
||||
Vector3::Subtract(objectBoundsCascade.Maximum, _cascadeBounds.Minimum, objectBoundsCascade.Maximum);
|
||||
const float chunkSize = _voxelSize * GLOBAL_SDF_RASTERIZE_CHUNK_SIZE;
|
||||
const Int3 objectChunkMin(objectBoundsCascade.Minimum / chunkSize);
|
||||
@@ -944,10 +951,11 @@ void GlobalSignDistanceFieldPass::RasterizeHeightfield(Actor* actor, GPUTexture*
|
||||
// Add object data for the GPU buffer
|
||||
uint16 objectIndex = _objectsBufferCount++;
|
||||
ObjectRasterizeData objectData;
|
||||
Matrix worldToLocal;
|
||||
Matrix::Invert(localToWorld, worldToLocal);
|
||||
Matrix localToWorldM, worldToLocal;
|
||||
Matrix::Transformation(localToWorld.Scale, localToWorld.Orientation, localToWorld.Translation - _sdfData->Origin, localToWorldM);
|
||||
Matrix::Invert(localToWorldM, worldToLocal);
|
||||
Matrix::Transpose(worldToLocal, objectData.WorldToVolume);
|
||||
Matrix::Transpose(localToWorld, objectData.VolumeToWorld);
|
||||
Matrix::Transpose(localToWorldM, objectData.VolumeToWorld);
|
||||
objectData.VolumeToUVWMul = Float3(localToUV.X, 1.0f, localToUV.Y);
|
||||
objectData.VolumeToUVWAdd = Float3(localToUV.Z, 0.0f, localToUV.W);
|
||||
objectData.MipOffset = (float)_cascadeIndex * 0.5f; // Use lower-quality mip for far cascades
|
||||
|
||||
@@ -76,9 +76,9 @@ public:
|
||||
void RenderDebug(RenderContext& renderContext, GPUContext* context, GPUTexture* output);
|
||||
|
||||
// Rasterize Model SDF into the Global SDF. Call it from actor Draw() method during DrawPass::GlobalSDF.
|
||||
void RasterizeModelSDF(Actor* actor, const ModelBase::SDFData& sdf, const Matrix& localToWorld, const BoundingBox& objectBounds);
|
||||
void RasterizeModelSDF(Actor* actor, const ModelBase::SDFData& sdf, const Transform& localToWorld, const BoundingBox& objectBounds);
|
||||
|
||||
void RasterizeHeightfield(Actor* actor, GPUTexture* heightfield, const Matrix& localToWorld, const BoundingBox& objectBounds, const Float4& localToUV);
|
||||
void RasterizeHeightfield(Actor* actor, GPUTexture* heightfield, const Transform& localToWorld, const BoundingBox& objectBounds, const Float4& localToUV);
|
||||
|
||||
private:
|
||||
#if COMPILE_WITH_DEV_ENV
|
||||
|
||||
@@ -512,7 +512,7 @@ void RenderInner(SceneRenderTask* task, RenderContext& renderContext)
|
||||
context->ResetRenderTarget();
|
||||
context->ResetSR();
|
||||
context->FlushState();
|
||||
|
||||
|
||||
// Custom Post Processing
|
||||
renderContext.List->RunMaterialPostFxPass(context, renderContext, MaterialPostFxLocation::AfterPostProcessingPass, frameBuffer, tempBuffer);
|
||||
renderContext.List->RunCustomPostFxPass(context, renderContext, PostProcessEffectLocation::Default, frameBuffer, tempBuffer);
|
||||
|
||||
@@ -257,6 +257,7 @@ void ShadowsPass::Prepare(RenderContext& renderContext, GPUContext* context)
|
||||
shadowView.ModelLODBias = view.ModelLODBias + view.ShadowModelLODBias;
|
||||
shadowView.ModelLODDistanceFactor = view.ModelLODDistanceFactor * view.ShadowModelLODDistanceFactor;
|
||||
shadowView.Pass = DrawPass::Depth;
|
||||
shadowView.Origin = view.Origin;
|
||||
_shadowContext.List = &_shadowCache;
|
||||
}
|
||||
|
||||
|
||||
@@ -152,7 +152,8 @@ void ShadowsOfMordor::Builder::onJobRender(GPUContext* context)
|
||||
auto chunkSize = terrain->GetChunkSize();
|
||||
const auto heightmap = patch->Heightmap.Get()->GetTexture();
|
||||
|
||||
const Matrix& world = chunk->GetWorld();
|
||||
Matrix world;
|
||||
chunk->GetTransform().GetWorld(world);
|
||||
Matrix::Transpose(world, shaderData.WorldMatrix);
|
||||
shaderData.LightmapArea = chunk->Lightmap.UVsArea;
|
||||
shaderData.TerrainChunkSizeLOD0 = TERRAIN_UNITS_PER_VERTEX * chunkSize;
|
||||
|
||||
@@ -512,7 +512,6 @@ void Terrain::Draw(RenderContext& renderContext)
|
||||
const float chunkSize = TERRAIN_UNITS_PER_VERTEX * (float)_chunkSize;
|
||||
const float posToUV = 0.25f / chunkSize;
|
||||
Float4 localToUV(posToUV, posToUV, 0.0f, 0.0f);
|
||||
Matrix localToWorld;
|
||||
for (const TerrainPatch* patch : _patches)
|
||||
{
|
||||
if (!patch->Heightmap)
|
||||
@@ -522,8 +521,7 @@ void Terrain::Draw(RenderContext& renderContext)
|
||||
patchTransform.Orientation = Quaternion::Identity;
|
||||
patchTransform.Scale = Float3(1.0f, patch->_yHeight, 1.0f);
|
||||
patchTransform = _transform.LocalToWorld(patchTransform);
|
||||
patchTransform.GetWorld(localToWorld);
|
||||
GlobalSignDistanceFieldPass::Instance()->RasterizeHeightfield(this, patch->Heightmap->GetTexture(), localToWorld, patch->_bounds, localToUV);
|
||||
GlobalSignDistanceFieldPass::Instance()->RasterizeHeightfield(this, patch->Heightmap->GetTexture(), patchTransform, patch->_bounds, localToUV);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -533,16 +531,17 @@ void Terrain::Draw(RenderContext& renderContext)
|
||||
{
|
||||
if (!patch->Heightmap)
|
||||
continue;
|
||||
Matrix worldToLocal;
|
||||
Matrix localToWorld, worldToLocal;
|
||||
BoundingSphere chunkSphere;
|
||||
BoundingBox localBounds;
|
||||
for (int32 chunkIndex = 0; chunkIndex < TerrainPatch::CHUNKS_COUNT; chunkIndex++)
|
||||
{
|
||||
TerrainChunk* chunk = &patch->Chunks[chunkIndex];
|
||||
Matrix::Invert(chunk->GetWorld(), worldToLocal);
|
||||
chunk->GetTransform().GetWorld(localToWorld); // TODO: large-worlds
|
||||
Matrix::Invert(localToWorld, worldToLocal);
|
||||
BoundingBox::Transform(chunk->GetBounds(), worldToLocal, localBounds);
|
||||
BoundingSphere::FromBox(chunk->GetBounds(), chunkSphere);
|
||||
GlobalSurfaceAtlasPass::Instance()->RasterizeActor(this, chunk, chunkSphere, chunk->GetWorld(), localBounds, 1 << 2, false);
|
||||
GlobalSurfaceAtlasPass::Instance()->RasterizeActor(this, chunk, chunkSphere, chunk->GetTransform(), localBounds, 1 << 2, false);
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
||||
@@ -86,7 +86,7 @@ void TerrainChunk::Draw(const RenderContext& renderContext) const
|
||||
return;
|
||||
drawCall.InstanceCount = 1;
|
||||
drawCall.Material = _cachedDrawMaterial;
|
||||
drawCall.World = _world;
|
||||
renderContext.View.GetWorldMatrix(_transform, drawCall.World);
|
||||
drawCall.ObjectPosition = drawCall.World.GetTranslation();
|
||||
drawCall.Terrain.Patch = _patch;
|
||||
drawCall.Terrain.HeightmapUVScaleBias = _heightmapUVScaleBias;
|
||||
@@ -142,7 +142,7 @@ void TerrainChunk::Draw(const RenderContext& renderContext, MaterialBase* materi
|
||||
return;
|
||||
drawCall.InstanceCount = 1;
|
||||
drawCall.Material = material;
|
||||
drawCall.World = _world;
|
||||
renderContext.View.GetWorldMatrix(_transform, drawCall.World);
|
||||
drawCall.ObjectPosition = drawCall.World.GetTranslation();
|
||||
drawCall.Terrain.Patch = _patch;
|
||||
drawCall.Terrain.HeightmapUVScaleBias = _heightmapUVScaleBias;
|
||||
@@ -214,8 +214,7 @@ void TerrainChunk::UpdateTransform()
|
||||
localTransform.Translation = _patch->_offset + Vector3(_x * size, _patch->_yOffset, _z * size);
|
||||
localTransform.Orientation = Quaternion::Identity;
|
||||
localTransform.Scale = Vector3(1.0f, _patch->_yHeight, 1.0f);
|
||||
localTransform = terrainTransform.LocalToWorld(localTransform);
|
||||
localTransform.GetWorld(_world);
|
||||
_transform = terrainTransform.LocalToWorld(localTransform);
|
||||
}
|
||||
|
||||
void TerrainChunk::CacheNeighbors()
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "Engine/Core/Math/BoundingBox.h"
|
||||
#include "Engine/Core/Math/Matrix.h"
|
||||
#include "Engine/Core/Math/Transform.h"
|
||||
#include "Engine/Serialization/ISerializable.h"
|
||||
#include "Engine/Content/Assets/MaterialBase.h"
|
||||
#include "Engine/Level/Scene/Lightmap.h"
|
||||
@@ -26,7 +27,7 @@ private:
|
||||
TerrainPatch* _patch;
|
||||
uint16 _x, _z;
|
||||
Float4 _heightmapUVScaleBias;
|
||||
Matrix _world;
|
||||
Transform _transform;
|
||||
BoundingBox _bounds;
|
||||
Vector3 _boundsCenter;
|
||||
float _perInstanceRandom;
|
||||
@@ -85,11 +86,11 @@ public:
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the chunk world matrix transform.
|
||||
/// Gets the chunk transformation (world to local).
|
||||
/// </summary>
|
||||
FORCE_INLINE const Matrix& GetWorld() const
|
||||
FORCE_INLINE const Transform& GetTransform() const
|
||||
{
|
||||
return _world;
|
||||
return _transform;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -238,9 +238,9 @@ float4 PS_Debug(Quad_VS2PS input) : SV_Target
|
||||
float zSlice = 0.6f;
|
||||
float mip = 0;
|
||||
uint cascade = 0;
|
||||
float distance01 = GlobalSDFTex[cascade].SampleLevel(SamplerLinearClamp, float3(input.TexCoord, zSlice), mip).x;
|
||||
//float distance01 = GlobalSDFTex[cascade].SampleLevel(SamplerLinearClamp, float3((input.TexCoord.x + cascade) / (float)GlobalSDF.CascadesCount, input.TexCoord.y, zSlice), mip).x;
|
||||
//float distance01 = GlobalSDFMip[cascade].SampleLevel(SamplerLinearClamp, float3(input.TexCoord, zSlice), mip).x;
|
||||
float distance01 = GlobalSDFTex.SampleLevel(SamplerLinearClamp, float3(input.TexCoord, zSlice), mip).x;
|
||||
//float distance01 = GlobalSDFTex.SampleLevel(SamplerLinearClamp, float3((input.TexCoord.x + cascade) / (float)GlobalSDF.CascadesCount, input.TexCoord.y, zSlice), mip).x;
|
||||
//float distance01 = GlobalSDFMip.SampleLevel(SamplerLinearClamp, float3(input.TexCoord, zSlice), mip).x;
|
||||
float distance = distance01 * GlobalSDF.CascadePosDistance[cascade].w;
|
||||
if (abs(distance) < 1)
|
||||
return float4(1, 0, 0, 1);
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
|
||||
META_CB_BEGIN(0, Data)
|
||||
float4x4 WVP;
|
||||
float3 ViewOffset;
|
||||
float Padding;
|
||||
GBufferData GBuffer;
|
||||
AtmosphericFogData AtmosphericFog;
|
||||
META_CB_END
|
||||
@@ -51,8 +53,7 @@ GBufferOutput PS_Sky(MaterialInput input)
|
||||
float3 vsPos = GetViewPos(gBufferData, uv, LinearZ2DeviceDepth(gBufferData, 1));
|
||||
float3 wsPos = mul(float4(vsPos, 1), gBufferData.InvViewMatrix).xyz;
|
||||
float3 viewVector = wsPos - gBufferData.ViewPos;
|
||||
float sceneDepth = length(viewVector);
|
||||
float4 color = GetAtmosphericFog(AtmosphericFog, gBufferData.ViewFar, gBufferData.ViewPos, viewVector, sceneDepth, float3(0, 0, 0));
|
||||
float4 color = GetAtmosphericFog(AtmosphericFog, gBufferData.ViewFar, wsPos + ViewOffset, gBufferData.ViewPos + ViewOffset);
|
||||
|
||||
// Pack GBuffer
|
||||
output.Light = color;
|
||||
|
||||
Reference in New Issue
Block a user