Refactor engine to support double-precision vectors
This commit is contained in:
@@ -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++)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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++;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -103,8 +103,8 @@ namespace ShadowsOfMordor
|
||||
/// </summary>
|
||||
struct HemisphereData
|
||||
{
|
||||
Vector3 Position;
|
||||
Vector3 Normal;
|
||||
Float3 Position;
|
||||
Float3 Normal;
|
||||
|
||||
int16 TexelX;
|
||||
int16 TexelY;
|
||||
|
||||
Reference in New Issue
Block a user