Refactor engine to support double-precision vectors

This commit is contained in:
Wojtek Figat
2022-06-13 00:40:32 +02:00
parent f82e370392
commit a881c90b2e
744 changed files with 19062 additions and 12467 deletions

View File

@@ -217,8 +217,8 @@ bool ShadowsOfMordor::Builder::SceneBuildCache::onImportLightmap(TextureData& im
mip.Data.Allocate(mip.DepthPitch);
#if HEMISPHERES_IRRADIANCE_FORMAT == HEMISPHERES_FORMAT_R32G32B32A32
auto pos = (Vector4*)mip.Data.Get();
const auto textureData = ImportLightmapTextureData.Get<Vector4>();
auto pos = (Float4*)mip.Data.Get();
const auto textureData = ImportLightmapTextureData.Get<Float4>();
for (int32 y = 0; y < image.Height; y++)
{
for (int32 x = 0; x < image.Width; x++)

View File

@@ -38,14 +38,14 @@ void ShadowsOfMordor::Builder::generateCharts()
// Calculate desired area for the entry's chart (based on object dimensions and settings)
// Reject missing models or too small objects
Vector3 size = entry.Box.GetSize();
Float3 size = entry.Box.GetSize();
float dimensionsCoeff = size.AverageArithmetic();
if (size.X <= 1.0f)
dimensionsCoeff = Vector2(size.Y, size.Z).AverageArithmetic();
dimensionsCoeff = Float2(size.Y, size.Z).AverageArithmetic();
else if (size.Y <= 1.0f)
dimensionsCoeff = Vector2(size.X, size.Z).AverageArithmetic();
dimensionsCoeff = Float2(size.X, size.Z).AverageArithmetic();
else if (size.Z <= 1.0f)
dimensionsCoeff = Vector2(size.Y, size.X).AverageArithmetic();
dimensionsCoeff = Float2(size.Y, size.X).AverageArithmetic();
const float scale = settings.GlobalObjectsScale * entry.Scale * LightmapTexelsPerWorldUnit * dimensionsCoeff;
if (scale <= ZeroTolerance)
continue;

View File

@@ -44,11 +44,11 @@ void ShadowsOfMordor::Builder::exportLightmapPreview(SceneBuildCache* scene, int
const int32 texelAdress = ((atlasSize - y - 1) * atlasSize + x) * NUM_SH_TARGETS;
#if HEMISPHERES_IRRADIANCE_FORMAT == HEMISPHERES_FORMAT_R32G32B32A32
auto textureData = scene->ImportLightmapTextureData.Get<Vector4>();
Color color = Color(Vector4::Clamp(textureData[texelAdress + sh], Vector4::Zero, Vector4::One));
auto textureData = scene->ImportLightmapTextureData.Get<Float4>();
Color color = Color(Float4::Clamp(textureData[texelAdress + sh], Float4::Zero, Float4::One));
#elif HEMISPHERES_IRRADIANCE_FORMAT == HEMISPHERES_FORMAT_R16G16B16A16
auto textureData = scene->ImportLightmapTextureData.Get<Half4>();
Color color = Color(Vector4::Clamp(textureData[texelAdress + sh].ToVector4(), Vector4::Zero, Vector4::One));
Color color = Color(Float4::Clamp(textureData[texelAdress + sh].ToFloat4(), Float4::Zero, Float4::One));
#endif
dataBmp[pos + 0] = static_cast<byte>(color.B * 255);
@@ -84,9 +84,9 @@ void ShadowsOfMordor::Builder::exportCachePreview(SceneBuildCache* scene, Genera
for (int32 y = 0; y < cacheData.PositionsData.Height; y++)
{
#if CACHE_POSITIONS_FORMAT == HEMISPHERES_FORMAT_R32G32B32A32
Vector3 color(mipData->Get<Vector4>(x, y));
Float3 color(mipData->Get<Float4>(x, y));
#elif CACHE_POSITIONS_FORMAT == HEMISPHERES_FORMAT_R16G16B16A16
Vector3 color = mipData->Get<Half4>(x, y).ToVector3();
Float3 color = mipData->Get<Half4>(x, y).ToFloat3();
#endif
color /= 100.0f;
@@ -110,9 +110,9 @@ void ShadowsOfMordor::Builder::exportCachePreview(SceneBuildCache* scene, Genera
for (int32 y = 0; y < cacheData.NormalsData.Height; y++)
{
#if CACHE_NORMALS_FORMAT == HEMISPHERES_FORMAT_R32G32B32A32
Vector3 color(mipData->Get<Vector4>(x, y));
Float3 color(mipData->Get<Float4>(x, y));
#elif CACHE_NORMALS_FORMAT == HEMISPHERES_FORMAT_R16G16B16A16
Vector3 color = mipData->Get<Half4>(x, y).ToVector3();
Float3 color = mipData->Get<Half4>(x, y).ToFloat3();
#endif
color.Normalize();
@@ -182,7 +182,7 @@ void ShadowsOfMordor::Builder::downloadDebugHemisphereAtlases(SceneBuildCache* s
Platform::MemoryClear(data, dataSize);
auto mipData = textureData.GetData(0, 0);
auto dddd = (Vector4*)mipData->Data.Get();
auto dddd = (Float4*)mipData->Data.Get();
for (int x = 0; x < textureData.Width; x++)
{
@@ -191,7 +191,7 @@ void ShadowsOfMordor::Builder::downloadDebugHemisphereAtlases(SceneBuildCache* s
int pos = ((textureData.Height - y - 1) * textureData.Width + x) * 3;
int srcPos = (y * textureData.Width + x);
Vector4 color = Vector4::Clamp(dddd[srcPos], Vector4::Zero, Vector4::One);
Float4 color = Float4::Clamp(dddd[srcPos], Float4::Zero, Float4::One);
data[pos + 0] = (byte)(color.Z * 255);
data[pos + 1] = (byte)(color.Y * 255);

View File

@@ -36,7 +36,7 @@ bool cacheStaticGeometryTree(Actor* actor, ShadowsOfMordor::Builder::SceneBuildC
if (model && !model->WaitForLoaded())
{
entry.Type = ShadowsOfMordor::Builder::GeometryType::StaticModel;
entry.UVsBox = Rectangle(Vector2::Zero, Vector2::One);
entry.UVsBox = Rectangle(Float2::Zero, Float2::One);
entry.AsStaticModel.Actor = staticModel;
entry.Scale = Math::Clamp(staticModel->GetScaleInLightmap(), 0.0f, LIGHTMAP_SCALE_MAX);
@@ -85,7 +85,7 @@ bool cacheStaticGeometryTree(Actor* actor, ShadowsOfMordor::Builder::SceneBuildC
{
entry.AsTerrain.Actor = terrain;
entry.Type = ShadowsOfMordor::Builder::GeometryType::Terrain;
entry.UVsBox = Rectangle(Vector2::Zero, Vector2::One);
entry.UVsBox = Rectangle(Float2::Zero, Float2::One);
entry.Scale = Math::Clamp(terrain->GetScaleInLightmap(), 0.0f, LIGHTMAP_SCALE_MAX);
for (int32 patchIndex = 0; patchIndex < terrain->GetPatchesCount(); patchIndex++)
{
@@ -115,7 +115,7 @@ bool cacheStaticGeometryTree(Actor* actor, ShadowsOfMordor::Builder::SceneBuildC
{
entry.AsFoliage.Actor = foliage;
entry.Type = ShadowsOfMordor::Builder::GeometryType::Foliage;
entry.UVsBox = Rectangle(Vector2::Zero, Vector2::One);
entry.UVsBox = Rectangle(Float2::Zero, Float2::One);
for (auto i = foliage->Instances.Begin(); i.IsNotEnd(); ++i)
{
auto& instance = *i;

View File

@@ -9,22 +9,22 @@
namespace
{
void SampleCache(ShadowsOfMordor::GenerateHemispheresData& data, int32 texelX, int32 texelY, Vector3& outPosition, Vector3& outNormal)
void SampleCache(ShadowsOfMordor::GenerateHemispheresData& data, int32 texelX, int32 texelY, Float3& outPosition, Float3& outNormal)
{
const auto mipDataPositions = data.PositionsData.GetData(0, 0);
#if CACHE_POSITIONS_FORMAT == HEMISPHERES_FORMAT_R32G32B32A32
outPosition = Vector3(mipDataPositions->Get<Vector4>(texelX, texelY));
outPosition = Float3(mipDataPositions->Get<Float4>(texelX, texelY));
#elif CACHE_POSITIONS_FORMAT == HEMISPHERES_FORMAT_R16G16B16A16
outPosition = mipDataPositions->Get<Half4>(texelX, texelY).ToVector3();
outPosition = mipDataPositions->Get<Half4>(texelX, texelY).ToFloat3();
#else
#error "Unknown format."
#endif
const auto mipDataNormals = data.NormalsData.GetData(0, 0);
#if CACHE_NORMALS_FORMAT == HEMISPHERES_FORMAT_R32G32B32A32
outNormal = Vector3(mipDataNormals->Get<Vector4>(texelX, texelY));
outNormal = Float3(mipDataNormals->Get<Float4>(texelX, texelY));
#elif CACHE_NORMALS_FORMAT == HEMISPHERES_FORMAT_R16G16B16A16
outNormal = mipDataNormals->Get<Half4>(texelX, texelY).ToVector3();
outNormal = mipDataNormals->Get<Half4>(texelX, texelY).ToFloat3();
#else
#error "Unknown format."
#endif
@@ -34,7 +34,7 @@ namespace
{
const auto mipDataNormals = data.NormalsData.GetData(0, 0);
#if CACHE_NORMALS_FORMAT == HEMISPHERES_FORMAT_R32G32B32A32
mipDataNormals->Get<Vector4>(texelX, texelY) = Vector4::Zero;
mipDataNormals->Get<Float4>(texelX, texelY) = Float4::Zero;
#elif CACHE_NORMALS_FORMAT == HEMISPHERES_FORMAT_R16G16B16A16
mipDataNormals->Get<Half4>(texelX, texelY) = Half4::Zero;
#else
@@ -74,7 +74,7 @@ void ShadowsOfMordor::Builder::generateHemispheres()
auto& lightmapEntry = scene->Lightmaps[_workerStagePosition0];
lightmapEntry.Hemispheres.Clear();
lightmapEntry.Hemispheres.EnsureCapacity(Math::Square(atlasSize / 2));
Vector3 position, normal;
Float3 position, normal;
// Fill cache
if (runStage(RenderCache))
@@ -122,7 +122,7 @@ void ShadowsOfMordor::Builder::generateHemispheres()
// Try to merge similar hemispheres (threshold values are controlled by the quality slider)
int32 mergedCount = 1;
Vector3 mergedSumPos = position, mergedSumNorm = normal;
Float3 mergedSumPos = position, mergedSumNorm = normal;
for (int32 x = -maxTexelsDistance; x <= maxTexelsDistance; x++)
{
for (int32 y = -maxTexelsDistance; y <= maxTexelsDistance; y++)
@@ -135,12 +135,12 @@ void ShadowsOfMordor::Builder::generateHemispheres()
continue;
// Sample cache for possible to use texel
Vector3 pp, nn;
Float3 pp, nn;
SampleCache(cacheData, xx, yy, pp, nn);
nn.Normalize();
if (Vector3::Distance(position, pp) <= maxMergeRadius
&& Vector3::Dot(normal, nn) >= normalSimilarityMin)
if (Float3::Distance(position, pp) <= maxMergeRadius
&& Float3::Dot(normal, nn) >= normalSimilarityMin)
{
// Merge them!
mergedCount++;

View File

@@ -30,8 +30,8 @@ namespace ShadowsOfMordor
uint32 TexelAddress;
uint32 AtlasSize;
float TerrainChunkSizeLOD0;
Vector4 HeightmapUVScaleBias;
Vector3 WorldInvScale;
Float4 HeightmapUVScaleBias;
Float3 WorldInvScale;
float Dummy1;
});
}
@@ -159,10 +159,10 @@ void ShadowsOfMordor::Builder::onJobRender(GPUContext* context)
chunk->GetHeightmapUVScaleBias(&shaderData.HeightmapUVScaleBias);
// Extract per axis scales from LocalToWorld transform
const float scaleX = Vector3(world.M11, world.M12, world.M13).Length();
const float scaleY = Vector3(world.M21, world.M22, world.M23).Length();
const float scaleZ = Vector3(world.M31, world.M32, world.M33).Length();
shaderData.WorldInvScale = Vector3(
const float scaleX = Float3(world.M11, world.M12, world.M13).Length();
const float scaleY = Float3(world.M21, world.M22, world.M23).Length();
const float scaleZ = Float3(world.M31, world.M32, world.M33).Length();
shaderData.WorldInvScale = Float3(
scaleX > 0.00001f ? 1.0f / scaleX : 0.0f,
scaleY > 0.00001f ? 1.0f / scaleY : 0.0f,
scaleZ > 0.00001f ? 1.0f / scaleZ : 0.0f);
@@ -273,7 +273,7 @@ void ShadowsOfMordor::Builder::onJobRender(GPUContext* context)
auto& lightmapEntry = scene->Lightmaps[_workerStagePosition0];
// All black everything!
context->ClearUA(lightmapEntry.LightmapData, Vector4::Zero);
context->ClearUA(lightmapEntry.LightmapData, Float4::Zero);
_wasStageDone = true;
break;
@@ -342,12 +342,12 @@ void ShadowsOfMordor::Builder::onJobRender(GPUContext* context)
auto& hemisphere = lightmapEntry.Hemispheres[_workerStagePosition1];
// Create tangent frame
Vector3 tangent;
Vector3 c1 = Vector3::Cross(hemisphere.Normal, Vector3(0.0, 0.0, 1.0));
Vector3 c2 = Vector3::Cross(hemisphere.Normal, Vector3(0.0, 1.0, 0.0));
Float3 tangent;
Float3 c1 = Float3::Cross(hemisphere.Normal, Float3(0.0, 0.0, 1.0));
Float3 c2 = Float3::Cross(hemisphere.Normal, Float3(0.0, 1.0, 0.0));
tangent = c1.Length() > c2.Length() ? c1 : c2;
tangent = Vector3::Normalize(tangent);
const Vector3 binormal = Vector3::Cross(tangent, hemisphere.Normal);
tangent = Float3::Normalize(tangent);
const Float3 binormal = Float3::Cross(tangent, hemisphere.Normal);
// Setup view
const Vector3 pos = hemisphere.Position + hemisphere.Normal * 0.001f;
@@ -374,15 +374,15 @@ void ShadowsOfMordor::Builder::onJobRender(GPUContext* context)
// Setup shader data
Matrix worldToTangent;
worldToTangent.SetRow1(Vector4(tangent, 0.0f));
worldToTangent.SetRow2(Vector4(binormal, 0.0f));
worldToTangent.SetRow3(Vector4(hemisphere.Normal, 0.0f));
worldToTangent.SetRow4(Vector4(0.0f, 0.0f, 0.0f, 1.0f));
worldToTangent.SetRow1(Float4(tangent, 0.0f));
worldToTangent.SetRow2(Float4(binormal, 0.0f));
worldToTangent.SetRow3(Float4(hemisphere.Normal, 0.0f));
worldToTangent.SetRow4(Float4(0.0f, 0.0f, 0.0f, 1.0f));
worldToTangent.Invert();
//
Matrix viewToWorld; // viewToWorld is inverted view, since view is worldToView
Matrix::Invert(view, viewToWorld);
viewToWorld.SetRow4(Vector4(0.0f, 0.0f, 0.0f, 1.0f)); // reset translation row
viewToWorld.SetRow4(Float4(0.0f, 0.0f, 0.0f, 1.0f)); // reset translation row
Matrix viewToTangent;
Matrix::Multiply(viewToWorld, worldToTangent, viewToTangent);
Matrix::Transpose(viewToTangent, shaderData.ToTangentSpace);

View File

@@ -103,8 +103,8 @@ namespace ShadowsOfMordor
/// </summary>
struct HemisphereData
{
Vector3 Position;
Vector3 Normal;
Float3 Position;
Float3 Normal;
int16 TexelX;
int16 TexelY;