public GeneratedColorPalette( PaletteGenerator generator, PaletteParameters parameters) { // Adjust base color up if black level is too close to it XnaHSL baseColor = AdjustBaseColor(parameters.BaseColor, generator.BlackLevel); // Tint just a little toward yellow based on yellow light XnaHSL untintedBaseColor = baseColor; if (baseColor.Saturation > 0) { baseColor = baseColor.LerpHue(60, parameters.YellowLight * 0.075f); } XnaHSL highlight, specular; GetHighlight(baseColor, generator, parameters, out highlight, out specular); XnaHSL shadow, darkest; GetShadow(untintedBaseColor, generator, parameters, out shadow, out darkest); // Set the calculated values BaseColor = baseColor; Darkest = darkest; Shadow = shadow; Highlight = highlight; Specular = specular; ReducedDepth = parameters.ReducedDepth; }
public IndexedGeneratedPalette( SpriteRamp ramp, PaletteParameters parameters) { BasePalette = ramp.GetColorPalette(parameters); ColorValues = ramp.ColorValues.ToArray(); PaletteAdjustments = ramp.Adjustments.ToArray(); #if DEBUG System.Diagnostics.Debug.Assert(ramp.Count == ColorValues.Length, "Palette and ramp size must match"); System.Diagnostics.Debug.Assert(ramp.Count == PaletteAdjustments.Length, "Palette and ramp size must match"); #endif // Saturation of the adjustment is reduced if the generated palette // is itself low saturation var rawParameters = (PaletteParameters)parameters.Clone(); rawParameters.YellowLight = 0; rawParameters.BlueShadow = 0; var rawPalette = ramp.GetColorPalette(rawParameters); AdjustmentsSaturationMultiplier = SaturationMultiplier( rawPalette.BaseColor, new XnaHSL(ramp.BaseColor)); //@Debug: per color saturation adjustments /*AdjustmentsSaturationMultipliers = PaletteAdjustments * .Select(x => 1f) * .ToArray(); * for (int i = 0; i < AdjustmentsSaturationMultipliers.Length; i++) * { * AdjustmentsSaturationMultipliers[i] = SaturationMultiplier( * rawPalette, ramp, i); * }*/ }
private void MinimizeSpecularityError(PaletteParameters parameters) { var entries = Palette.RampEntries(Ramp); Ramp.Generator.MinimizeSpecularityError(parameters, entries); RefreshAdjustments(); }
private float MinimizeError( PaletteParameters parameters, List <PaletteEntry> ramp, Range <float> range, Func <PaletteGenerator, float, float> function) { const int count = 20; const int iterations = 3; List <Tuple <float, float> > errors = null; int index = -1; for (int i = 0; i < iterations; i++) { errors = Errors(parameters, ramp, range, count, function); float min = errors.Min(x => x.Item2); index = errors.FindIndex(x => x.Item2 == min); // Get the indices above and below the minimum value int step = Math.Max(1, (int)(count * 0.3f) / 2); int startIndex = Math.Max(0, index - step); startIndex = Math.Min(count - step * 2, startIndex); int endIndex = startIndex + step * 2; range = new Range <float>(errors[startIndex].Item1, errors[endIndex].Item1); } return(errors[index].Item1); }
private List <Tuple <float, float> > Errors( PaletteParameters parameters, List <PaletteEntry> ramp, Range <float> range, int count, Func <PaletteGenerator, float, float> function) { PaletteGenerator copyGenerator = (PaletteGenerator)Clone(); PaletteParameters copyParameters = (PaletteParameters)parameters.Clone(); float interval = (range.Maximum - range.Minimum) / count; var errors = new List <Tuple <float, float> >(); for (int i = 0; i <= count; i++) { float value = range.Minimum + interval * i; function(copyGenerator, value); // Kind of necessary for user facing values // Minimize error on blue shadow copyParameters.MinimizeBlueError(copyGenerator, ramp); // Minimize error on yellow light copyParameters.MinimizeYellowError(copyGenerator, ramp); var palette = copyGenerator.GetPalette(copyParameters); float error = palette.GetError(ramp); errors.Add(Tuple.Create(value, error)); } return(errors); }
private void AdjustSpecularity(Color color, PaletteParameters parameters, float rawAmount) { // Find what this color's value looks like with minimum and maximum // specularity, and using where it should be inverse lerp into that // range var range = SpecularityRange(); var darkGenerator = (PaletteGenerator)Clone(); darkGenerator.Specularity = range.Minimum; var darkPalette = darkGenerator.GetPalette(parameters); var lightGenerator = (PaletteGenerator)Clone(); lightGenerator.Specularity = range.Maximum; var lightPalette = lightGenerator.GetPalette(parameters); // Dark Base Value will be a larger number, because a dark color // will be closer to the specular float darkBaseValue = darkPalette.GetValue(color); float lightBaseValue = lightPalette.GetValue(color); // I don't know how, but // Avoid divide by 0 if (lightBaseValue == darkBaseValue) { this.Specularity = 1f; return; } float value = (rawAmount - lightBaseValue) / (darkBaseValue - lightBaseValue); this.Specularity = MathHelper.Lerp(range.Maximum, range.Minimum, value); }
public override void CopyFrom(TactileDataContent other) { CheckSameClass(other); var source = (RecolorEntry)other; OtherNames = new List <string>(source.OtherNames); Parameters = (PaletteParameters)source.Parameters.Clone(); }
internal void MinimizeShadowError(PaletteParameters parameters, List <PaletteEntry> ramp) { var range = ShadowRange(); Func <PaletteGenerator, float, float> function = (PaletteGenerator generator, float value) => generator.ShadowAmount = value; float minimum = MinimizeError(parameters, ramp, range, function); ShadowAmount = minimum; }
internal void MinimizeSpecularityError(PaletteParameters parameters, List <PaletteEntry> ramp) { var range = SpecularityRange(); Func <PaletteGenerator, float, float> function = (PaletteGenerator generator, float value) => generator.Specularity = value; float minimum = MinimizeError(parameters, ramp, range, function); Specularity = minimum; }
public PaletteParameters DefaultParameters() { var parameters = new PaletteParameters(this.BaseColor); parameters.ReducedDepth = true; // Minimize error on blue shadow MinimizeBlueError(parameters); // Minimize error on yellow light MinimizeYellowError(parameters); return(parameters); }
private static void GetHighlight( XnaHSL baseHSL, PaletteGenerator generator, PaletteParameters parameters, out XnaHSL highlight, out XnaHSL specular) { Color baseSpecular = PaletteGenerator.BaseSpecularColor(baseHSL.GetColor()); // Tint yellow XnaHSL specularHSL = new XnaHSL(baseSpecular); // If greyscale, simply treat the hue as yellow if (float.IsNaN(specularHSL.Hue)) { specularHSL = specularHSL.SetHue(60); } specularHSL = specularHSL.LerpHue(60, parameters.YellowLight); specularHSL = specularHSL.SetSaturation(MathHelper.Lerp( specularHSL.Saturation, 1f, parameters.YellowLight)); specularHSL = specularHSL.SetLightness(MathHelper.Lerp( specularHSL.Lightness, Math.Max(0.5f, specularHSL.Lightness), parameters.YellowLight)); // Add specular specularHSL = specularHSL.SetLightness(MathHelper.Lerp( specularHSL.Lightness, 1f, generator.Specularity)); // Reduce the lightness if the base color is darker than the generator color if (generator.BaseLightness > 0 && baseHSL.Lightness < generator.BaseLightness) { float lightnessDiff = generator.BaseLightness - baseHSL.Lightness; specularHSL = specularHSL.SetLightness(specularHSL.Lightness - (lightnessDiff)); } float highlightAmount = 0.5f; // If the base color is sufficiently bright, lighten the specular // to keep the contrast from getting too low float lightnessRatio = (baseHSL.Lightness - 0.5f) * 2f; if (lightnessRatio > 0) { specularHSL = specularHSL.SetLightness( MathHelper.Lerp(specularHSL.Lightness, 1f, lightnessRatio)); highlightAmount = MathHelper.Lerp(0.5f, 1f, lightnessRatio); } // Get highlight XnaHSL highlightHSL = XnaHSL.Lerp(baseHSL, specularHSL, highlightAmount); highlight = highlightHSL; specular = specularHSL; }
public void AdjustValue(Color color, PaletteParameters parameters, float value) { var palette = GetPalette(parameters); if (palette.DarkerThanBase(color)) { // Adjust shadow AdjustShadowAmount(color, palette, value); } else { // Adjust specular AdjustSpecularity(color, parameters, value); } }
private static void GetShadow( XnaHSL baseHSL, PaletteGenerator generator, PaletteParameters parameters, out XnaHSL shadow, out XnaHSL darkest) { XnaHSL blackHSL = new XnaHSL( baseHSL.Hue, baseHSL.Saturation * generator.ShadowAmount, generator.BlackLevel, baseHSL.Alpha); // If the base color is sufficiently bright, lighten the darker shades float lightnessRatio = (baseHSL.Lightness - 0.5f) * 2f; if (lightnessRatio > 0) { blackHSL = blackHSL.SetSaturation(blackHSL.Saturation * (1f - lightnessRatio * 0.95f)); float blackLuma = Color_Util.GetLuma(blackHSL.GetColor()); // Increase the lightness by more if it's a color with a low // luma to lightness ratio float lumaRatio = 1f; if (blackLuma > 0) { lumaRatio = blackHSL.Lightness / blackLuma; } blackHSL = blackHSL.SetLightness( MathHelper.Lerp(blackHSL.Lightness, MathHelper.Lerp(blackHSL.Lightness, 1f, 0.25f), lightnessRatio * lumaRatio)); } // Tint black and shadow blue blackHSL = blackHSL.LerpHue(240, parameters.BlueShadow); blackHSL = blackHSL.SetSaturation(MathHelper.Lerp(blackHSL.Saturation, 1f, parameters.BlueShadow / 4f)); XnaHSL shadowHSL = XnaHSL.Lerp(blackHSL, baseHSL, generator.ShadowAmount); shadowHSL = shadowHSL.SetSaturation(MathHelper.Lerp(blackHSL.Saturation, baseHSL.Saturation, 0.5f)); shadowHSL = shadowHSL.SetHue(blackHSL.Hue); shadowHSL = shadowHSL.LerpHue(baseHSL.Hue, 0.25f); shadow = shadowHSL; darkest = blackHSL; }
public GeneratedColorPalette GetColorPalette(PaletteParameters parameters) { parameters = (PaletteParameters)parameters.Clone(); // Adjust the lightness of the base color XnaHSL baseHsl = new XnaHSL(this.BaseColor); XnaHSL parametersHsl = new XnaHSL(parameters.BaseColor); parametersHsl = parametersHsl.SetLightness( MathHelper.Lerp( parametersHsl.Lightness, baseHsl.Lightness, parameters.OriginalLightness)); parameters.BaseColor = parametersHsl.GetColor(); return(Ramp.Generator.GetPalette(parameters)); }
internal void RecalibrateError() { Ramp.Generator.BaseLightness = new XnaHSL(this.BaseColor).Lightness; // Set initial palette values // If there are colors darker than the base color if (Ramp.BaseColorIndex > 0) { // Sets the darkest color a fraction of the distance to the base color float step = GeneratedColorPalette.BASE_VALUE / (Ramp.BaseColorIndex + 1); SetValue(0, step); } else { Ramp.Generator.ShadowAmount = 0.5f; } // If there are colors lighter than the base color if (Ramp.BaseColorIndex < Ramp.Count - 1) { // Sets the lightest color a fraction of the distance to the base color float step = (1f - GeneratedColorPalette.BASE_VALUE) / (Ramp.Count - Ramp.BaseColorIndex); SetValue(Ramp.Count - 1, 1f - step); } else { Ramp.Generator.Specularity = 0.5f; } var parameters = new PaletteParameters(this.BaseColor); // Minimize error on shadow amount MinimizeShadowError(parameters); // Minimize error on specularity MinimizeSpecularityError(parameters); }
private List <Tuple <float, float> > Errors( PaletteGenerator generator, List <PaletteEntry> ramp, Range <float> range, int count, Func <PaletteParameters, float, float> function) { PaletteParameters copyParameters = (PaletteParameters)Clone(); float interval = (range.Maximum - range.Minimum) / count; var errors = new List <Tuple <float, float> >(); for (int i = 0; i <= count; i++) { float value = range.Minimum + interval * i; function(copyParameters, value); var palette = generator.GetPalette(copyParameters); float error = palette.GetError(ramp); errors.Add(Tuple.Create(value, error)); } return(errors); }
private PaletteParameters(PaletteParameters source) { CopyFrom(source); }
public IndexedGeneratedPalette GetIndexedPalette(PaletteParameters parameters) { return(new IndexedGeneratedPalette(this, parameters)); }
public void MinimizeYellowError(PaletteParameters parameters) { var entries = Palette.RampEntries(Ramp); parameters.MinimizeYellowError(Ramp.Generator, entries); }
public override void Read(BinaryReader input) { OtherNames.read(input); Parameters = PaletteParameters.ReadContent(input); }
public RecolorEntry(PaletteParameters parameters) { OtherNames = new List <string>(); Parameters = parameters; }
public GeneratedColorPalette GetPalette(PaletteParameters parameters) { return(new GeneratedColorPalette(this, parameters)); }