5

I'm trying to pass a GLKVector4 to a shader that should receive it as a vec4. I'm using a fragment shader modifier:

material.shaderModifiers = [ SCNShaderModifierEntryPoint.fragment: shaderModifier ]

where shaderModifier is:

// color changes
uniform float colorModifier;
uniform vec4 colorOffset;

vec4 color = _output.color;

color = color + colorOffset;
color = color + vec4(0.0, colorModifier, 0.0, 0.0);

_output.color = color;

(I'm simply adding a color offset) I've tried:

material.setValue(GLKVector4(v: (250.0, 0.0, 0.0, 0.0)), "colorOffset")

which doesn't work (no offset is added and the shader uses the default value that is (0, 0, 0, 0)). Same happens if I replace GLKVector4 by SCNVector4

Following this I've also tried:

let points: [float2] = [float2(250.0), float2(0.0), float2(0.0), float2(0.0)]
material.setValue(NSData(bytes: points, length: points.count * sizeof(float2)), "colorOffset")

However, I can pass a float value to the uniform colorModifier easily by doing:

material.setValue(250.0, forKey: "colorModifier")

and that will increase the green channel as excepted

Community
  • 1
  • 1
Guig
  • 9,891
  • 7
  • 64
  • 126

1 Answers1

2

So you have to use NSValue, that has a convenience initialization for SCNVector4, so:

let v = SCNVector4(x: 250.0, y: 0.0, z: 0.0, w: 0.0)
material.setValue(NSValue(scnVector4: v), "colorOffset")

It'd be too good if SceneKit could handle it's own types directly...

Guig
  • 9,891
  • 7
  • 64
  • 126
  • Wrapping structs in `NSValue` for passing to APIs that take objects is an artifact of ObjC. Swift currently provides some automatic bridging, but not for everything (and generally not for types provided by higher-level frameworks like SceneKit). Looks like [that might be changing, though](https://github.com/apple/swift-evolution/blob/master/proposals/0139-bridge-nsnumber-and-nsvalue.md)... – rickster Sep 09 '16 at 21:30
  • 1
    Very interesting read. I somehow wished SceneKit was not relying so much on Swift handling those things, and instead defined the `setValue` functions that make sense, like `set(value: Float, for key: String)`, `set(value: SCNVector4...)` etc and therefore scoping out all the other things that anyway will not be passed to the shader program, instead of accepting an `Any` type input – Guig Sep 09 '16 at 22:06
  • 1
    That [might be good feedback to send to Apple](http://bugreport.apple.com). – rickster Sep 09 '16 at 22:15