Skip to content

Commit

Permalink
fix shader interpolation and make image comparison tests more toleran…
Browse files Browse the repository at this point in the history
…t. (#10506)

* add debug save image mode
add percent diff assertion
add log of percent and each diff

* enable save
fix build errors
fix path errors

* update shaders to fix them on WARP/real hardware
remove dynamo ps input
add color distance and percent dist check to make tests more tolerant of changes

* rename function, rename params
  • Loading branch information
mjkkirschner authored Mar 27, 2020
1 parent 9d4bdff commit 1c4c98f
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 46 deletions.
Binary file modified src/DynamoCoreWpf/ViewModels/Watch3D/compiledShaders/psDynamoMesh
Binary file not shown.
Binary file not shown.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
#define MESH
#include"Common.hlsl"
#include"CommonBuffers.hlsl"
#include"DynamoCommonStructures.hlsl"

//--------------------------------------------------------------------------------------
// Phong Lighting Reflection Model
Expand All @@ -26,16 +25,17 @@ SamplerState LinearSampler
MaxAnisotropy = 16;
};

float4 main(PSInputCustom input, bool isFrontFacing : SV_IsFrontFace) : SV_Target
float4 main(PSInput input, bool isFrontFacing : SV_IsFrontFace) : SV_Target
{
//TODO move to common or pass in from material or the vParams.
float4 vSelectionColor = float4(0.0, 0.62, 1.0, 1.0);


//flags were passed through from vertex shader
//flags were passed through from a common buffer per model
//lets decode them
uint flags = int(input.customParams.x);

int flags = int(vParams.x);

//our flags are packed in this order:
/*
None = 0,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,11 @@
#define MESH
#include"Common.hlsl"
#include"DataStructs.hlsl"
#include"DynamoCommonStructures.hlsl"
#pragma pack_matrix( row_major )

PSInputCustom main(VSInput input)
PSInput main(VSInput input)
{
PSInputCustom output;
PSInput output;

//our flags are packed in this order:
/*
Expand Down Expand Up @@ -58,9 +57,6 @@ PSInputCustom main(VSInput input)
//set normal for interpolation
output.n = normalize(mul(input.n, (float3x3)mWorld));

//send our flags through to the frag shader
output.customParams.x = vParams.x;

return output;
}

Expand Down
91 changes: 67 additions & 24 deletions src/VisualizationTests/HelixImageComparisonTests.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@

//UNCOMMENT THIS DEFINE TO UPDATE THE REFERENCE IMAGES.
//#define UPDATEIMAGEDATA

//UNCOMMENT TO SAVE DEBUG IMAGES.
//#define SAVEDEBUGIMAGES
using Dynamo.Graph.Nodes.ZeroTouch;
using Dynamo.Selection;
using DynamoCoreWpfTests.Utility;
using HelixToolkit.Wpf.SharpDX;
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
Expand Down Expand Up @@ -68,9 +70,10 @@ private static System.Drawing.Bitmap BitmapFromSource(BitmapSource bitmapsource)
return bitmap;
}

private string GenerateTestDataPathFromTest(string testname)
private string GenerateImagePathFromTest(string testname,bool debug = false)
{
var fileName = testname+".png";
var debugstring = debug ? "debug" : string.Empty;
var fileName = testname+debugstring+".png";
string relativePath = Path.Combine(
GetTestDirectory(ExecutingDirectory),
string.Format(@"core\visualization\imageComparison\referenceImages\{0}", fileName));
Expand All @@ -80,7 +83,7 @@ private string GenerateTestDataPathFromTest(string testname)
private void RenderCurrentViewAndCompare(string testName)
{
DispatcherUtil.DoEvents();
var path = GenerateTestDataPathFromTest(testName);
var path = GenerateImagePathFromTest(testName);
var bitmapsource = DynamoRenderBitmap(BackgroundPreview.View,1024, 1024);
#if UPDATEIMAGEDATA
UpdateTestData(path, bitmapsource);
Expand All @@ -89,32 +92,72 @@ private void RenderCurrentViewAndCompare(string testName)
var refbitmap = BitmapFromSource(refimage);
var newImage = BitmapFromSource(bitmapsource);

#if SAVEDEBUGIMAGES
var debugPath = GenerateTestDataPathFromTest(testName,true);
SaveBitMapSourceAsPNG(debugPath, bitmapsource);
#endif

compareImageColors(refbitmap, newImage);
}

//TODO consider something like:
//(diferentPixelsCount / (mainImage.width* mainImage.height))*100
//for a percent image diff.
private static void compareImageColors(Bitmap image1,Bitmap image2)
private static void compareImageColors(Bitmap expectedImage,Bitmap actualImage)
{
Assert.AreEqual(image1.Width, image2.Width);
Assert.AreEqual(image1.Height, image2.Height);
Assert.AreEqual(image1.PixelFormat, image2.PixelFormat);
Assert.AreEqual(expectedImage.Width, actualImage.Width);
Assert.AreEqual(expectedImage.Height, actualImage.Height);
Assert.AreEqual(expectedImage.PixelFormat, actualImage.PixelFormat);

for (var x = 0; x < image1.Width; x++)
//x,y,expected,result
var differences = new List<Tuple<int, int, Color, Color>>();

for (var x = 0; x < expectedImage.Width; x++)
{
for (var y = 0; y < image1.Height; y++)
for (var y = 0; y < expectedImage.Height; y++)
{
var expectedCol = image1.GetPixel(x, y);
var otherCol = image2.GetPixel(x, y);
Assert.AreEqual(expectedCol, otherCol,$"pixel {x}:{y} was not as expected");
var expectedCol = expectedImage.GetPixel(x, y);
var otherCol = actualImage.GetPixel(x, y);
if((ColorDistance(expectedCol,otherCol) > 128))
{
differences.Add(Tuple.Create(x, y, expectedCol, otherCol));
// this can be painfully slow, but is useful during debug - uncomment for more info.
// Console.WriteLine($"{expectedCol}, {otherCol}, pixel {x}:{y} was not in expected range");
}
}
}
var diff = CalculatePercentDiff(expectedImage, differences);
Console.WriteLine($"% difference by out of range pixels was {(diff * 100).ToString("N" + 3)}%");
Assert.LessOrEqual(diff, .01);

}

/// <summary>
/// Euclidean distance between colors.
/// Does not use the alpha channel.
/// </summary>
/// <param name="color1"></param>
/// <param name="color2"></param>
/// <returns></returns>
private static double ColorDistance(Color color1, Color color2)
{
var r1 = color1.R;
var g1 = color1.G;
var b1 = color1.B;

var r2 = color2.R;
var g2 = color2.G;
var b2 = color2.B;
return Math.Sqrt(Math.Pow((r2 - r1), 2) + Math.Pow((g2 - g1),2) + Math.Pow((b2 - b1),2));
}

private static double CalculatePercentDiff(Bitmap image1, List<Tuple<int,int,Color,Color>> differences)
{
//TODO should we remove background pixels from this calculation via color?
// or other filtering techniques for more precision
var totalPixels = image1.Width * image1.Height;
return (double)differences.Count / (double)totalPixels;
}

#endregion
#endregion

#region meshes
#region meshes
[Test]
public void StandardMeshGeometryRender()
{
Expand Down Expand Up @@ -171,8 +214,8 @@ public void VertColorFrozenMeshGeometryRender()
node3.IsFrozen = true;
RenderCurrentViewAndCompare(MethodBase.GetCurrentMethod().Name);
}
#endregion
#region pointsAndLines
#endregion
#region pointsAndLines
[Test]
public void points()
{
Expand Down Expand Up @@ -256,9 +299,9 @@ public void linesFrozen()
RenderCurrentViewAndCompare(MethodBase.GetCurrentMethod().Name);
}

#endregion
#endregion

#region SpecialRenderPackages
#region SpecialRenderPackages
[Test]
public void directManipulator()
{
Expand All @@ -272,7 +315,7 @@ public void directManipulator()
RenderCurrentViewAndCompare(MethodBase.GetCurrentMethod().Name);
}

#endregion
#endregion

}
}

0 comments on commit 1c4c98f

Please sign in to comment.