private Color GetTolerance(Point point, Color expected) { // pixelCenter is factored into this point int x = (int)Math.Floor(point.X - Const.pixelCenterX); int y = (int)Math.Floor(point.Y - Const.pixelCenterY); Color missingPixelTolerance = ColorOperations.ColorFromArgb(0, 0, 0, 0); Color lookupTolerance = ColorOperations.ColorFromArgb(0, 0, 0, 0); for (int j = y; j < y + 2; j++) { for (int i = x; i < x + 2; i++) { Color?current = SafeGetPixel(i, j); if (current.HasValue) { // Keep the max of the diff tolerance and the existing tolerance Color diff = ColorOperations.AbsoluteDifference(current.Value, expected); lookupTolerance = ColorOperations.Max(lookupTolerance, diff); lookupTolerance = ColorOperations.Max(lookupTolerance, toleranceBuffer[i, j]); } else { // increase tolerance by 25% since this pixel's value is unknown missingPixelTolerance = ColorOperations.Add(missingPixelTolerance, ColorOperations.ColorFromArgb(.25, .25, .25, .25)); } } } return(ColorOperations.Add(lookupTolerance, missingPixelTolerance)); }
/// <summary> /// Apply a 2D transform to the RenderBuffer /// </summary> public void ApplyTransform(Transform transform) { if (transform == null || transform.Value == Matrix.Identity) { return; } RenderBuffer clone = Clone(); Matrix inverse = transform.Value; inverse.Invert(); inverse = MathEx.ConvertToAbsolutePixels(inverse); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { Point point = inverse.Transform(new Point(x + Const.pixelCenterX, y + Const.pixelCenterY)); Color?color = clone.GetPixel(point); if (color.HasValue) { frameBuffer[x, y] = color.Value; toleranceBuffer[x, y] = clone.GetTolerance(point, frameBuffer[x, y]); } else { // Transformed outside of the RenderBuffer frameBuffer[x, y] = ColorOperations.ColorFromArgb(0, 0, 0, 0); toleranceBuffer[x, y] = RenderTolerance.DefaultColorTolerance; } } } }
public static Color WeightedSum(Color c1, Color c2, Color c3, Weights weights) { double a, r, g, b; a = WeightedSum(ColorOperations.ByteToDouble(c1.A), ColorOperations.ByteToDouble(c2.A), ColorOperations.ByteToDouble(c3.A), weights); r = WeightedSum(ColorOperations.ByteToDouble(c1.R), ColorOperations.ByteToDouble(c2.R), ColorOperations.ByteToDouble(c3.R), weights); g = WeightedSum(ColorOperations.ByteToDouble(c1.G), ColorOperations.ByteToDouble(c2.G), ColorOperations.ByteToDouble(c3.G), weights); b = WeightedSum(ColorOperations.ByteToDouble(c1.B), ColorOperations.ByteToDouble(c2.B), ColorOperations.ByteToDouble(c3.B), weights); return(ColorOperations.ColorFromArgb(a, r, g, b)); }
private RenderBuffer Render(InterpolationMode interpolation, bool renderBackground) { for (int i = 0; i < primitives.Length; i++) { // Render one model to composite buffer renderer.Render(primitives[i], interpolation); } AddClippingTolerance(); if (opacity != 1.0) { buffer.ApplyOpacityMask(new SolidColorBrush(ColorOperations.ColorFromArgb(opacity, 0, 0, 0))); } buffer.ApplyOpacityMask(opacityMask); buffer.ApplyEffect(effect, effectInput); buffer.ApplyClip(clip); buffer.ApplyTransform(transform); if (renderBackground) { buffer.AddBackground(background); } // Add default tolerances adds tolerance for all rendered pixels. // The reason we do this after adding the background is because specular lighting // does not write to the z-buffer, and therefore we will not get default tolerance // near the falloff region on meshes that only use a SpecularMaterial. buffer.AddDefaultTolerances(); if (SceneRenderer.enableAntiAliasedRendering) { // If we are set for 4XAA, we already rendered this 4X as big. // Do a downsampling blend to get the AA result. buffer = buffer.DownSample4X(); } buffer.EnsureCorrectBitDepth(); return(buffer); }
public override Color FilteredTextureLookup(Point uv) { double x = uv.X * width; double y = uv.Y * height; // Define where we want to have texel centers double texelCenterX = 0.5; double texelCenterY = 0.5; // Compute integer array indices of texel above and to the left of (x,y) int topLeftX = (int)Math.Floor(x - (1 - texelCenterX)); int topLeftY = (int)Math.Floor(y - (1 - texelCenterY)); // Get colors of 4 nearest neighbours Color ctl = GetColor(topLeftX, topLeftY); Color ctr = GetColor(topLeftX + 1, topLeftY); Color cbl = GetColor(topLeftX, topLeftY + 1); Color cbr = GetColor(topLeftX + 1, topLeftY + 1); // Shift (x,y) to align it with array indices x -= texelCenterX; y -= texelCenterY; // Compute position within our texel double dx = x - Math.Floor(x); double dy = y - Math.Floor(y); // Argh! double ctlA = ColorOperations.ByteToDouble(ctl.A); double ctlR = ColorOperations.ByteToDouble(ctl.R); double ctlG = ColorOperations.ByteToDouble(ctl.G); double ctlB = ColorOperations.ByteToDouble(ctl.B); double cblA = ColorOperations.ByteToDouble(cbl.A); double cblR = ColorOperations.ByteToDouble(cbl.R); double cblG = ColorOperations.ByteToDouble(cbl.G); double cblB = ColorOperations.ByteToDouble(cbl.B); double ctrA = ColorOperations.ByteToDouble(ctr.A); double ctrR = ColorOperations.ByteToDouble(ctr.R); double ctrG = ColorOperations.ByteToDouble(ctr.G); double ctrB = ColorOperations.ByteToDouble(ctr.B); double cbrA = ColorOperations.ByteToDouble(cbr.A); double cbrR = ColorOperations.ByteToDouble(cbr.R); double cbrG = ColorOperations.ByteToDouble(cbr.G); double cbrB = ColorOperations.ByteToDouble(cbr.B); // Precompute values for perf reasons double ddx = 1 - dx; double ddy = 1 - dy; double k1 = ddx * ddy; double k2 = dx * ddy; double k3 = ddx * dy; double k4 = dx * dy; // Perform interpolation, store result in a, r, g, and b double a = k1 * ctlA + k2 * ctrA + k3 * cblA + k4 * cbrA; double r = k1 * ctlR + k2 * ctrR + k3 * cblR + k4 * cbrR; double g = k1 * ctlG + k2 * ctrG + k3 * cblG + k4 * cbrG; double b = k1 * ctlB + k2 * ctrB + k3 * cblB + k4 * cbrB; return(ColorOperations.ColorFromArgb(a, r, g, b)); }