예제 #1
0
파일: HdrColor.cs 프로젝트: dotnet/wpf-test
 public HdrColor(Color color)
 {
     a = ColorOperations.ByteToDouble(color.A);
     r = ColorOperations.ByteToDouble(color.R);
     g = ColorOperations.ByteToDouble(color.G);
     b = ColorOperations.ByteToDouble(color.B);
 }
예제 #2
0
        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));
        }
예제 #3
0
        /// <summary>
        /// Apply an opacity mask based on the alpha values of a brush.
        /// </summary>
        public void ApplyOpacityMask(Brush brush)
        {
            if (brush == null)
            {
                return;
            }
            Color[,] colors = TextureGenerator.RenderBrushToColorArray(brush, width, height);

            for (int y = 0; y < height; y++)
            {
                for (int x = 0; x < width; x++)
                {
                    double opacity = ColorOperations.ByteToDouble(colors[x, y].A);
                    frameBuffer[x, y] = ColorOperations.PreMultipliedOpacityScale(frameBuffer[x, y], opacity);
                }
            }
        }
예제 #4
0
        /// <summary>
        /// This function sums over the tolerance buffer and returns what
        /// percentage of an image's color information is being thrown out
        /// (We don't include alpha in our sum)
        /// </summary>
        public static string GetErrorStatistics(RenderBuffer buffer)
        {
            double percentage = 0.0;

            for (int y = 0; y < buffer.Height; y++)
            {
                for (int x = 0; x < buffer.Width; x++)
                {
                    percentage += ColorOperations.ByteToDouble(buffer.ToleranceBuffer[x, y].R);
                    percentage += ColorOperations.ByteToDouble(buffer.ToleranceBuffer[x, y].G);
                    percentage += ColorOperations.ByteToDouble(buffer.ToleranceBuffer[x, y].B);
                }
            }

            // We multiply by 100 for percent, then divide by 3 for "R" "G" and "B"
            percentage = 100.0 * percentage / (3.0 * (double)buffer.Width * (double)buffer.Height);
            return(String.Format("Color data ignored due to tolerance criteria: {0}%.", percentage.ToString("##0.00###")));
        }
예제 #5
0
        private void ApplyDropShadow(DropShadowBitmapEffect effect, Rect effectInput)
        {
            RenderBuffer clone = Clone();

            clone.boundsOverride = effectInput;
            double depth       = MathEx.ConvertToAbsolutePixels(effect.ShadowDepth);
            double angle       = MathEx.ToRadians(effect.Direction);
            Vector pixelOffset = new Vector(depth * Math.Cos(angle), depth * Math.Sin(-angle));
            Color  effectColor = effect.Color;

            effectColor = ColorOperations.ScaleAlpha(effectColor, effect.Opacity);
            double blurRadius = 1.0 + (effect.Softness * 9.0);

            int xEnd = (int)effectInput.Right;
            int yEnd = (int)effectInput.Bottom;

            for (int y = (int)effectInput.Y; y < yEnd; y++)
            {
                for (int x = (int)effectInput.X; x < xEnd; x++)
                {
                    Point point = new Point(x + Const.pixelCenterX, y + Const.pixelCenterY) - pixelOffset;
                    Color?color = clone.GetPixelSample(point, blurRadius);

                    if (color.HasValue)
                    {
                        double opacity = ColorOperations.ByteToDouble(color.Value.A);
                        Color  shadow  = ColorOperations.ScaleAlpha(effectColor, opacity);
                        shadow            = ColorOperations.PreMultiplyColor(shadow);
                        frameBuffer[x, y] = ColorOperations.PreMultipliedAlphaBlend(clone.frameBuffer[x, y], shadow);

                        if (frameBuffer[x, y] != clone.frameBuffer[x, y])
                        {
                            // Transfer the tolerance (silhouette, etc) over too
                            Color tolerance = clone.GetToleranceSample(point, blurRadius);
                            toleranceBuffer[x, y] = ColorOperations.Max(tolerance, clone.toleranceBuffer[x, y]);
                        }
                    }
                }
            }
        }
예제 #6
0
        /// <summary>
        /// Clip the regions specified by the Geometry out of the frame buffer.
        /// </summary>
        public void ApplyClip(Geometry clip)
        {
            if (clip == null)
            {
                return;
            }
            Color[,] clipColors = TextureGenerator.RenderBrushToColorArray(GetClipBrush(clip), width, height);

            // Clipping is anti-aliased.  Need tolerance around clip edges.
            Color[,] tolColors = TextureGenerator.RenderBrushToColorArray(GetClipTolerance(clip), width, height);

            for (int y = 0; y < height; y++)
            {
                for (int x = 0; x < width; x++)
                {
                    double opacity = ColorOperations.ByteToDouble(clipColors[x, y].A);
                    frameBuffer[x, y] = ColorOperations.PreMultipliedOpacityScale(frameBuffer[x, y], opacity);

                    Color tolerance = new Color();
                    tolerance.A           = tolerance.R = tolerance.G = tolerance.B = tolColors[x, y].A;
                    toleranceBuffer[x, y] = ColorOperations.Add(toleranceBuffer[x, y], tolerance);
                }
            }
        }
예제 #7
0
        /// <summary>
        /// Gouraud shading computes lighting per-vertex, in this method.
        /// Final pixel values are gathered from interpolating between pixels.
        /// Lighting is precomputed in this step per material.
        /// </summary>
        /// <param name="v">Input/Output per-vertex data.</param>
        protected override void ComputeVertexProgram(Vertex v)
        {
            // No color here ...
            v.Color = emptyColor;
            // Tolerance
            v.ColorTolerance = emptyColor;

            v.PrecomputedLight          = new Color[textures.Length];
            v.PrecomputedLightTolerance = new Color[textures.Length];
            int      textureIndex = 0;
            Point3D  position     = v.PositionAsPoint3D;
            Vector3D normal       = v.Normal;

            // Precompute lighting for all textures
            foreach (TextureFilter texture in textures)
            {
                HdrColor color     = emptyColor;
                HdrColor tolerance = emptyColor;

                if (texture != null)
                {
                    // Lighting is done in Premultiplied color space.
                    //
                    //  - BIG NOTE! - We do not actually premultiply the light contribution
                    //    because lighting is always opaque and premultiplying opaque colors
                    //    is a no-op.
                    //
                    //  - Tolerance CANNOT be done in Premultiplied color space because
                    //    it needs to know the final pixel color in order to premultiply properly.
                    //    We won't know the final pixel color until ComputePixelProgram is called.

                    // We ignore Alpha values during the computation and set the final value to
                    //  materialColor.A at the end.  This is why you will not see any clamping of
                    //  light values, etc in the code below.

                    Color materialColor = ColorOperations.PreMultiplyColor(texture.MaterialColor);

                    switch (texture.MaterialType)
                    {
                    case MaterialType.Diffuse:
                        foreach (LightEquation light in lightEquations)
                        {
                            Color lightContribution = light.IluminateDiffuse(position, normal);

                            if (light is AmbientLightEquation)
                            {
                                // AmbientColor knobs are reminiscent of additive material passes
                                //  because the alpha value will not be considered in the final color value
                                //  (i.e. premultiply to scale RGB by alpha, then never use alpha again)
                                Color ambientColor = ColorOperations.PreMultiplyColor(texture.AmbientColor);
                                color += ColorOperations.Modulate(lightContribution, ambientColor);
                            }
                            else
                            {
                                color += ColorOperations.Modulate(lightContribution, materialColor);
                            }
                            tolerance += light.GetLastError();
                        }
                        break;

                    case MaterialType.Specular:
                        foreach (LightEquation light in lightEquations)
                        {
                            // Don't need to check light equation type, since Ambient will return black
                            Color lightContribution = light.IluminateSpecular(position, normal, texture.SpecularPower);
                            color += ColorOperations.Modulate(lightContribution, materialColor);

                            tolerance += light.GetLastError();
                        }
                        break;

                    case MaterialType.Emissive:
                        color = materialColor;
                        break;
                    }

                    // Alpha is only considered at the end.  Overwrite whatever happened during the precomputation.
                    //  - Note that the alpha of the AmbientColor knob is NOT considered in the final value.

                    color.A = ColorOperations.ByteToDouble(materialColor.A);
                }

                v.PrecomputedLight[textureIndex]          = color.ClampedValue;
                v.PrecomputedLightTolerance[textureIndex] = tolerance.ClampedValue;

                textureIndex++;
            }
        }
예제 #8
0
        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));
        }