[kit] Pass target and feather values into the shaders

This commit is contained in:
Eryn Wells 2017-08-25 11:19:09 -07:00
parent 6c06aadd37
commit 0b752984dc
4 changed files with 134 additions and 20 deletions

View file

@ -293,6 +293,17 @@ public class Field {
didChange = true
}
if let target = userInfo["target"] as? Float {
parameters.target = target
defaults.target = target
didChange = true
}
if let feather = userInfo["feather"] as? Float {
parameters.feather = feather
defaults.feather = feather
didChange = true
}
if didChange {
populateParametersBuffer()
}

View file

@ -9,6 +9,36 @@
import Cocoa
extension UserDefaults {
public var target: Float {
get {
if let obj = object(forKey: "target") as? NSNumber {
return obj.floatValue
} else {
let defaultValue: Float = 1.0
set(defaultValue, forKey: "target")
return defaultValue
}
}
set {
set(newValue, forKey: "target")
}
}
public var feather: Float {
get {
if let obj = object(forKey: "feather") as? NSNumber {
return obj.floatValue
} else {
let defaultValue: Float = 0.25
set(defaultValue, forKey: "target")
return defaultValue
}
}
set {
set(newValue, forKey: "feather")
}
}
public var colorStyle: ColorStyle? {
get {
let value = integer(forKey: "colorStyle")

View file

@ -39,6 +39,34 @@ public class PreferencesViewController: NSViewController {
private var colorStackView = NSStackView()
private var colorViews = [ColorView]()
private lazy var targetSlider: SliderView = {
let targetSlider = SliderView(label: NSLocalizedString("Target", comment: "name of the target slider"))
targetSlider.slider.tag = Slider.target.rawValue
if #available(OSX 10.12.2, *) {
targetSlider.slider.trackFillColor = nil
}
targetSlider.slider.minValue = 0
targetSlider.slider.maxValue = 1
targetSlider.slider.target = self
targetSlider.slider.action = #selector(PreferencesViewController.sliderDidUpdate(sender:))
targetSlider.slider.floatValue = self.defaults.target
return targetSlider
}()
private lazy var featherSlider: SliderView = {
let featherSlider = SliderView(label: NSLocalizedString("Feather", comment: "name of the feather slider"))
featherSlider.slider.tag = Slider.feather.rawValue
if #available(OSX 10.12.2, *) {
featherSlider.slider.trackFillColor = nil
}
featherSlider.slider.minValue = 0
featherSlider.slider.maxValue = 1
featherSlider.slider.target = self
featherSlider.slider.action = #selector(PreferencesViewController.sliderDidUpdate(sender:))
featherSlider.slider.floatValue = self.defaults.feather
return featherSlider
}()
private lazy var styleMenu: NSPopUpButton = {
let button = NSPopUpButton()
button.translatesAutoresizingMaskIntoConstraints = false
@ -100,13 +128,15 @@ public class PreferencesViewController: NSViewController {
colorStackView.addArrangedSubview(styleMenu)
for i in 0..<4 {
let colorView = ColorView()
let colorView = ColorView(label: "Color \(i+1)")
colorView.translatesAutoresizingMaskIntoConstraints = false
colorView.label.stringValue = "Color \(i+1)"
colorStackView.addArrangedSubview(colorView)
colorViews.append(colorView)
}
colorStackView.addArrangedSubview(targetSlider)
colorStackView.addArrangedSubview(featherSlider)
showCloseButtonIfNeeded()
self.view = view
@ -163,6 +193,10 @@ public class PreferencesViewController: NSViewController {
postColorNotification()
}
func sliderDidUpdate(sender: NSSlider) {
postColorNotification()
}
func closeWindow() {
self.view.window?.close()
}
@ -191,23 +225,30 @@ public class PreferencesViewController: NSViewController {
for (idx, cv) in colorViews.enumerated() {
info["color\(idx)"] = cv.colorWell.color
}
info["target"] = targetSlider.slider.floatValue
info["feather"] = featherSlider.slider.floatValue
NotificationCenter.default.post(name: PreferencesDidChange_Color, object: nil, userInfo: info)
}
}
class ColorView: NSView {
class ParameterView: NSView {
private let stackView = NSStackView()
internal let colorWell = NSColorWell()
internal let label = NSTextField(labelWithString: "Hello")
internal let control: NSControl
internal let label: NSTextField
override init(frame frameRect: NSRect) {
super.init(frame: frameRect)
init(frame f: NSRect, control c: NSControl, label: String = "Hello") {
control = c
self.label = NSTextField(labelWithString: label)
super.init(frame: f)
commonInit()
}
convenience init(control c: NSControl) {
self.init(frame: NSRect(), control: c)
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
fatalError("init(coder:) has not been implemented")
}
private func commonInit() {
@ -217,9 +258,9 @@ class ColorView: NSView {
stackView.alignment = .centerY
stackView.distribution = .equalSpacing
colorWell.translatesAutoresizingMaskIntoConstraints = false
colorWell.setContentHuggingPriority(251, for: .horizontal)
stackView.addArrangedSubview(colorWell)
control.translatesAutoresizingMaskIntoConstraints = false
control.setContentHuggingPriority(251, for: .horizontal)
stackView.addArrangedSubview(control)
label.translatesAutoresizingMaskIntoConstraints = false
stackView.addArrangedSubview(label)
@ -233,3 +274,31 @@ class ColorView: NSView {
])
}
}
class ColorView: ParameterView {
var colorWell: NSColorWell {
return control as! NSColorWell
}
init(label: String) {
super.init(frame: NSRect(), control: NSColorWell(), label: label)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
class SliderView: ParameterView {
var slider: NSSlider {
return control as! NSSlider
}
init(label: String) {
super.init(frame: NSRect(), control: NSSlider(), label: label)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}

View file

@ -64,8 +64,8 @@ passthroughVertexShader(uint vid [[vertex_id]],
float sampleAtPoint(float2, constant Ball*, int);
// Color samplers
float4 singleColor(float, float, float4);
float4 gradient2(float, float, float, float4, float4);
float4 singleColor(float, float, float, float4);
float4 gradient2(float, float, float, float, float4, float4);
// Helpers
float mapValueFromRangeOntoRange(float, float, float, float, float);
@ -76,17 +76,18 @@ sampleToColorShader(RasterizerData in [[stage_in]],
constant Parameters& parameters [[buffer(0)]],
constant Ball* balls [[buffer(1)]])
{
const float target = 1.0;
const float target = parameters.target;
const float feather = parameters.feather;
const float sample = sampleAtPoint(in.position.xy, balls, parameters.numberOfBalls);
const float blend = in.position.x / parameters.size.x;
float4 out;
switch (parameters.colorStyle) {
case SingleColor:
out = singleColor(sample, target, parameters.colors[0]);
out = singleColor(sample, target, feather, parameters.colors[0]);
break;
case Gradient2Horizontal:
out = gradient2(sample, target, blend, parameters.colors[0], parameters.colors[1]);
out = gradient2(sample, target, feather, blend, parameters.colors[0], parameters.colors[1]);
break;
}
@ -112,15 +113,17 @@ sampleAtPoint(float2 point,
float4
singleColor(float sample,
float target,
float feather,
float4 color)
{
float4 out;
if (sample > 1.0) {
if (sample > target) {
out = color;
}
// Feather the alpha value.
const float a = clamp(mapValueFromRangeOntoRange(sample, 0.75 * target, target, 0, 1), 0.0, 1.0);
const float mappedAlpha = mapValueFromRangeOntoRange(sample, (1.0 - feather) * target, target, 0, 1);
const float a = clamp(mappedAlpha, 0.0, 1.0);
out = float4(out.xyz, a);
return out;
@ -129,12 +132,13 @@ singleColor(float sample,
float4
gradient2(float sample,
float target,
float feather,
float normalizedBlend,
float4 fromColor,
float4 toColor)
{
float4 blendedColor = averageTwoColors(normalizedBlend, fromColor, toColor);
float4 out = singleColor(sample, target, blendedColor);
float4 out = singleColor(sample, target, feather, blendedColor);
return out;
}