[kit] Pass target and feather values into the shaders
This commit is contained in:
parent
6c06aadd37
commit
0b752984dc
4 changed files with 134 additions and 20 deletions
|
@ -293,6 +293,17 @@ public class Field {
|
||||||
didChange = true
|
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 {
|
if didChange {
|
||||||
populateParametersBuffer()
|
populateParametersBuffer()
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,36 @@
|
||||||
import Cocoa
|
import Cocoa
|
||||||
|
|
||||||
extension UserDefaults {
|
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? {
|
public var colorStyle: ColorStyle? {
|
||||||
get {
|
get {
|
||||||
let value = integer(forKey: "colorStyle")
|
let value = integer(forKey: "colorStyle")
|
||||||
|
|
|
@ -39,6 +39,34 @@ public class PreferencesViewController: NSViewController {
|
||||||
private var colorStackView = NSStackView()
|
private var colorStackView = NSStackView()
|
||||||
private var colorViews = [ColorView]()
|
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 = {
|
private lazy var styleMenu: NSPopUpButton = {
|
||||||
let button = NSPopUpButton()
|
let button = NSPopUpButton()
|
||||||
button.translatesAutoresizingMaskIntoConstraints = false
|
button.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
@ -100,13 +128,15 @@ public class PreferencesViewController: NSViewController {
|
||||||
|
|
||||||
colorStackView.addArrangedSubview(styleMenu)
|
colorStackView.addArrangedSubview(styleMenu)
|
||||||
for i in 0..<4 {
|
for i in 0..<4 {
|
||||||
let colorView = ColorView()
|
let colorView = ColorView(label: "Color \(i+1)")
|
||||||
colorView.translatesAutoresizingMaskIntoConstraints = false
|
colorView.translatesAutoresizingMaskIntoConstraints = false
|
||||||
colorView.label.stringValue = "Color \(i+1)"
|
|
||||||
colorStackView.addArrangedSubview(colorView)
|
colorStackView.addArrangedSubview(colorView)
|
||||||
colorViews.append(colorView)
|
colorViews.append(colorView)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
colorStackView.addArrangedSubview(targetSlider)
|
||||||
|
colorStackView.addArrangedSubview(featherSlider)
|
||||||
|
|
||||||
showCloseButtonIfNeeded()
|
showCloseButtonIfNeeded()
|
||||||
|
|
||||||
self.view = view
|
self.view = view
|
||||||
|
@ -163,6 +193,10 @@ public class PreferencesViewController: NSViewController {
|
||||||
postColorNotification()
|
postColorNotification()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func sliderDidUpdate(sender: NSSlider) {
|
||||||
|
postColorNotification()
|
||||||
|
}
|
||||||
|
|
||||||
func closeWindow() {
|
func closeWindow() {
|
||||||
self.view.window?.close()
|
self.view.window?.close()
|
||||||
}
|
}
|
||||||
|
@ -191,23 +225,30 @@ public class PreferencesViewController: NSViewController {
|
||||||
for (idx, cv) in colorViews.enumerated() {
|
for (idx, cv) in colorViews.enumerated() {
|
||||||
info["color\(idx)"] = cv.colorWell.color
|
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)
|
NotificationCenter.default.post(name: PreferencesDidChange_Color, object: nil, userInfo: info)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ColorView: NSView {
|
class ParameterView: NSView {
|
||||||
private let stackView = NSStackView()
|
private let stackView = NSStackView()
|
||||||
internal let colorWell = NSColorWell()
|
internal let control: NSControl
|
||||||
internal let label = NSTextField(labelWithString: "Hello")
|
internal let label: NSTextField
|
||||||
|
|
||||||
override init(frame frameRect: NSRect) {
|
init(frame f: NSRect, control c: NSControl, label: String = "Hello") {
|
||||||
super.init(frame: frameRect)
|
control = c
|
||||||
|
self.label = NSTextField(labelWithString: label)
|
||||||
|
super.init(frame: f)
|
||||||
commonInit()
|
commonInit()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
convenience init(control c: NSControl) {
|
||||||
|
self.init(frame: NSRect(), control: c)
|
||||||
|
}
|
||||||
|
|
||||||
required init?(coder: NSCoder) {
|
required init?(coder: NSCoder) {
|
||||||
super.init(coder: coder)
|
fatalError("init(coder:) has not been implemented")
|
||||||
commonInit()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private func commonInit() {
|
private func commonInit() {
|
||||||
|
@ -217,9 +258,9 @@ class ColorView: NSView {
|
||||||
stackView.alignment = .centerY
|
stackView.alignment = .centerY
|
||||||
stackView.distribution = .equalSpacing
|
stackView.distribution = .equalSpacing
|
||||||
|
|
||||||
colorWell.translatesAutoresizingMaskIntoConstraints = false
|
control.translatesAutoresizingMaskIntoConstraints = false
|
||||||
colorWell.setContentHuggingPriority(251, for: .horizontal)
|
control.setContentHuggingPriority(251, for: .horizontal)
|
||||||
stackView.addArrangedSubview(colorWell)
|
stackView.addArrangedSubview(control)
|
||||||
|
|
||||||
label.translatesAutoresizingMaskIntoConstraints = false
|
label.translatesAutoresizingMaskIntoConstraints = false
|
||||||
stackView.addArrangedSubview(label)
|
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")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -64,8 +64,8 @@ passthroughVertexShader(uint vid [[vertex_id]],
|
||||||
float sampleAtPoint(float2, constant Ball*, int);
|
float sampleAtPoint(float2, constant Ball*, int);
|
||||||
|
|
||||||
// Color samplers
|
// Color samplers
|
||||||
float4 singleColor(float, float, float4);
|
float4 singleColor(float, float, float, float4);
|
||||||
float4 gradient2(float, float, float, float4, float4);
|
float4 gradient2(float, float, float, float, float4, float4);
|
||||||
|
|
||||||
// Helpers
|
// Helpers
|
||||||
float mapValueFromRangeOntoRange(float, float, float, float, float);
|
float mapValueFromRangeOntoRange(float, float, float, float, float);
|
||||||
|
@ -76,17 +76,18 @@ sampleToColorShader(RasterizerData in [[stage_in]],
|
||||||
constant Parameters& parameters [[buffer(0)]],
|
constant Parameters& parameters [[buffer(0)]],
|
||||||
constant Ball* balls [[buffer(1)]])
|
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 sample = sampleAtPoint(in.position.xy, balls, parameters.numberOfBalls);
|
||||||
const float blend = in.position.x / parameters.size.x;
|
const float blend = in.position.x / parameters.size.x;
|
||||||
|
|
||||||
float4 out;
|
float4 out;
|
||||||
switch (parameters.colorStyle) {
|
switch (parameters.colorStyle) {
|
||||||
case SingleColor:
|
case SingleColor:
|
||||||
out = singleColor(sample, target, parameters.colors[0]);
|
out = singleColor(sample, target, feather, parameters.colors[0]);
|
||||||
break;
|
break;
|
||||||
case Gradient2Horizontal:
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,15 +113,17 @@ sampleAtPoint(float2 point,
|
||||||
float4
|
float4
|
||||||
singleColor(float sample,
|
singleColor(float sample,
|
||||||
float target,
|
float target,
|
||||||
|
float feather,
|
||||||
float4 color)
|
float4 color)
|
||||||
{
|
{
|
||||||
float4 out;
|
float4 out;
|
||||||
if (sample > 1.0) {
|
if (sample > target) {
|
||||||
out = color;
|
out = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Feather the alpha value.
|
// 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);
|
out = float4(out.xyz, a);
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
|
@ -129,12 +132,13 @@ singleColor(float sample,
|
||||||
float4
|
float4
|
||||||
gradient2(float sample,
|
gradient2(float sample,
|
||||||
float target,
|
float target,
|
||||||
|
float feather,
|
||||||
float normalizedBlend,
|
float normalizedBlend,
|
||||||
float4 fromColor,
|
float4 fromColor,
|
||||||
float4 toColor)
|
float4 toColor)
|
||||||
{
|
{
|
||||||
float4 blendedColor = averageTwoColors(normalizedBlend, fromColor, toColor);
|
float4 blendedColor = averageTwoColors(normalizedBlend, fromColor, toColor);
|
||||||
float4 out = singleColor(sample, target, blendedColor);
|
float4 out = singleColor(sample, target, feather, blendedColor);
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue